Webpack 4 - create vendor chunk
In order to reduce the vendor JS bundle size. We can split the node module packages into different bundle files. I referred this blog for splitting the bulky vendor file generated by Webpack. Gist of that link which I used initially:
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
// get the name. E.g. node_modules/packageName/not/this/part.js
// or node_modules/packageName
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
// npm package names are URL-safe, but some servers don't like @ symbols
return `npm.${packageName.replace('@', '')}`;
},
},
},
},
}
If one wants to group multiple packages and chunk then into different bundles then refer following gist.
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
reactVendor: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: "reactvendor"
},
utilityVendor: {
test: /[\\/]node_modules[\\/](lodash|moment|moment-timezone)[\\/]/,
name: "utilityVendor"
},
bootstrapVendor: {
test: /[\\/]node_modules[\\/](react-bootstrap)[\\/]/,
name: "bootstrapVendor"
},
vendor: {
test: /[\\/]node_modules[\\/](!react-bootstrap)(!lodash)(!moment)(!moment-timezone)[\\/]/,
name: "vendor"
},
},
},
}
There are a few examples located here: https://github.com/webpack/webpack/tree/master/examples
Based on your example i believe this translate to:
// mode: "development || "production",
entry: {
client: './client.js',
},
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
publicPath: '/',
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true
},
}
},
runtimeChunk: true
}
In order to separate the vendors and the runtime you need to use the optimization
option.
Possible Webpack 4 configuration:
// mode: 'development' | 'production' | 'none'
entry: {
client: ['./client.js'],
vendor: ['babel-polyfill', 'react', 'react-dom', 'redux'],
},
output: {
filename: '[name].[chunkhash].bundle.js',
path: '../dist',
chunkFilename: '[name].[chunkhash].bundle.js',
publicPath: '/',
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
enforce: true,
chunks: 'all'
}
}
}
}
More info related with W4 can be found in this Webpack-Demo.
Also, you can achieve the same changing the optimization.splitChunks.chunks
property to "all"
. Read more here
Note: You can configure it via
optimization.splitChunks
. The examples say something about chunks, by default it only works for async chunks, but withoptimization.splitChunks.chunks: "all"
the same would be true for initial chunks.
You could remove vendor out of the entry property and set the optimization property like so...
entry: {
client: './client.js'
},
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
publicPath: '/',
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /node_modules/,
chunks: 'initial',
name: 'vendor',
enforce: true
},
}
}
}
Check this source webpack examples