Search code examples
reactjswebpackwebpack-2commonschunkplugin

Extract duplicate javascript code using WebPack CommonsChunkPlugin


I'm using WebPack CommonsChunkPlugin to extract duplicate code and reduce JavaScript code size. I have two html pages and two entries for them. Also i've added ReactJs vendor entry. So far, in webpack.config.js we have:

var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
    context: __dirname,
    entry: {
        react: ["react", "react-dom"],
        home: './assets/js/home.jsx',
        about: './assets/js/about.jsx',
    },

    output: {
        path: path.resolve('./assets/bundles/'),
        filename: "[name].js",
    },

    plugins: [
        new BundleTracker({filename: './webpack-stats.json'}),

        new webpack.optimize.CommonsChunkPlugin({
            name: 'react',
            minChunks: Infinity
        }),

        new BundleAnalyzerPlugin(),
    ],

    module: {
        rules: [
            {
              test: /\.jsx?$/, 
              exclude: /node_modules/,
              loader: 'babel-loader',
              options: { 
                  plugins: [["lodash", { "id": ["semantic-ui-react"] }]],
                  presets: ["es2015", "react"]
              }  
            },
        ],
    },

    resolve: {
        modules: ['node_modules', 'bower_components'],
        extensions: ['*', '.js', '.jsx']
    },
};

This configuration result with webpack-bundle-analyzer:

webpack bundle analyzer output

As you can see, there are some duplicate code, some in red area and some other in green area. I want to extract this js codes from home and about bundles into a separate bundle. To extract red area code, namely lodash library, i added these lines to webpack config:

new webpack.optimize.CommonsChunkPlugin({
    name: 'lodash',
    minChunks: function(module, count) {
        return module.context.indexOf('node_modules/lodash') >= 0;
    }
}), 

But it's not working as expected and lodash library code is still in both home and about bundles, also webpack creates a bundle named lodash that is almost empty and contains no js library.

Any idea on how to fix it ? How about extracting green are codes?


Solution

  • I managed to solve the problem by adding a common chunk to plugins. So final webpack config is :

    var path = require("path");
    var webpack = require('webpack');
    var BundleTracker = require('webpack-bundle-tracker');
    
    module.exports = {
    
        context: __dirname,
    
        entry: {
            react: ["react", "react-dom"],
            home: './assets/js/home.jsx',
            about: './assets/js/about.jsx',
        },
    
        output: {
            path: path.resolve('./assets/bundles/'),
            filename: "[name].js",
        },
    
        plugins: [
    
            new BundleTracker({filename: './webpack-stats.json'}),
    
            new webpack.optimize.CommonsChunkPlugin({
                name: 'react',
                filename: '[name].js',
                minChunks: Infinity,
            }),
    
            new webpack.optimize.CommonsChunkPlugin({
                name: 'common',
                chunks: ['home', 'about'],
                filename: '[name].js',
            }),
        ],
    
        module: {
            rules: [
                {
                    test: /\.jsx?$/, 
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    options: { 
                        plugins: [
                          ["lodash", { "id": ["semantic-ui-react"] }]
                        ],
                        presets: ["es2015", "react"]
                    }
                },
            ],
        },
    
        resolve: {
            modules: ['node_modules', 'bower_components'],
            extensions: ['*', '.js', '.jsx']
        },
    };
    

    And now bundle analyzer output is like this:

    analyzer output

    As it's shown in the picture, common semantic-ui-react and lodash libraries are now just in common bundle and not duplicated anymore.