Reputation: 926
Imagine I have a rich application, which uses a lot of the 3rd party modules including lodash, moment, axios, react.
If I bundle everything in one bundle at the end the size would be higher then 1MB.
I want webpack to pack my libraries in the way, that it stores:
I tried to play with the CommonsChunkPlugin in different ways, but never received the result I want.
I've prepared the example repository to illustrate my issue: https://github.com/PavelPolyakov/webpack-react-bundles
Webpack entry part (conf/webpack.base.config.js):
entry: {
lodash: 'lodash',
moment: 'moment',
app: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:3001',
'webpack/hot/only-dev-server',
'./app/index.js']
}
Here is production config (conf/webpack.production.config.js), trying to separate modules:
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context &&
module.context.indexOf('node_modules') !== -1;
}
}),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compress: {
warnings: true
}
})]
This case, the moment and lodash would still appear in the vendor bundle. I want to have them in the two separate bundles.
Any thoughts appreciated.
Upvotes: 1
Views: 1302
Reputation: 926
At the end I received the help from @sokra in github issue: https://github.com/webpack/webpack/issues/4638
For those who will be facing the same problem, here is the complete webpack config which solves the issue described in the question:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: ['./app/index.js']
},
output: {
filename: '[name].bundle.js',
sourceMapFilename: '[name].bundle.map',
path: path.resolve(__dirname, './dist')
},
devServer: {
port: 3001,
contentBase: path.resolve(__dirname, './dist'),
historyApiFallback: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [['es2015', { 'modules': false }], 'react'],
plugins: ['transform-async-to-generator',
'transform-decorators-legacy',
'transform-runtime',
'react-html-attrs',
'react-hot-loader/babel'],
}
}
]
},
{
test: /\.css/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.(eot|svg|ttf|woff|woff2|gif|jpg|png)$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
inject: "body"
}),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compress: {
warnings: true
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: (m) => /node_modules/.test(m.context)
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'lodash',
minChunks: (m) => /node_modules\/(?:lodash|moment)/.test(m.context)
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'moment',
minChunks: (m) => /node_modules\/(?:moment)/.test(m.context)
}),
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
minChunks: Infinity
})
],
resolve: {
extensions: ['.js', '.jsx']
},
devtool: 'source-map'
}
Thanks to all who tried to help!
Upvotes: 3
Reputation: 6864
It is probably easiest if you include them from a CDN and use an external.
This is not per definition code splitting but might be close to what you intend to accomplish: reducing bundle size. There is the advantage of some users having the CDN version already cached from another site.
Upvotes: 1