Extract duplicate JavaScript code using WebPack CommonsChunkPlugin

I am using WebPack CommonsChunkPlugin to extract duplicate code and reduce JavaScript code size. I have two html pages and two entries for them. I also added a ReactJs entry. So far in webpack.config.js we have had:

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 using webpack-bundle-analyzer :

webpack analyzer output

As you can see, there are several duplicates of the code, some in the red area and some others in the green area. I want to extract these js codes from home and about bundles in a separate package. To extract the red zone code, namely lodash , I added these lines to the webpack configuration:

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

But it does not work as expected, and the lodash library code is still in both the home and bundles, and webpack creates a package called lodash, which is almost empty and does not contain the js library.

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

+5
source share
2 answers

I managed to solve the problem by adding a common piece to the plugins. So, the final configuration of the web package:

 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 the output of the analyzer is as follows:

analyzer output

As shown in the figure, the common semantics-ui-reaction and lodash libraries are now just in a common bundle, not duplicated.

0
source

Your problem is that you are importing third-party libraries into each .js/.jsx file, without importing it previously into a shared file (usually called vendor.js ).
If you have this file that imports all your dependencies, and you include it as a record in CommonsChunkPlugin, the web package will not include your libraries in your latest packages ( home.js and about.js ). This method is called code splitting in webpack documents.

vendor.js (or a name suitable for your case)

 import 'react'; import 'react-dom'; import 'lodash'; import 'semantic-ui-react'; //... all your npm packages 

webpack.config.js

 var webpack = require('webpack'); var path = require('path'); module.exports = { context: __dirname, entry: { vendor: './assets/js/vendor.js, home: './assets/js/home.jsx', about: './assets/js/about.jsx', }, output: { path: path.resolve('./assets/bundles/'), filename: '[name].js', }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity }), ], //Rest of Your config ... }; 

index.html

 <body> <!-- AFTER YOUR HTML CODE --> <script type="text/javascript" src="/assets/bundles/vendor.js"></script> <script type="text/javascript" src="/assets/bundles/home.js"></script> <script type="text/javascript" src="/assets/bundles/about.js"></script> </body> 


Check the docs for splitting the web package code:

+2
source

Source: https://habr.com/ru/post/1270455/


All Articles