First, first things first:
Webpack4 is coming out next month, CommonsChunkplugin is dead!
Chunk
If you’re still interested, come and see it.
Let’s start by figuring out what a chunk is: WebPack calls a chunk a collection of code packaged together with multiple modules.
There are three types of Chunks in Webpack:
- Entry Chunk: a collection of module codes containing WebPack Runtime codes.
- Normal chunk: a collection of modules that do not contain Runtime code.
- Initial chunk: A special type of normal chunk, according to the document. It will load before Normal Chunk (for those of you who are interested).
A few other points to note:
- Entry Chunk must be loaded before Normal chunk, because it contains runtime code that defines a list of functions that WebPack needs to use. If it is not loaded first, the rest of the code webpack cannot play.
- Each entry point generates an entry chunk.
- For each module lazily loaded with import(), a normal chunk will be generated. This chunk will depend on the entry chunk called import() as its child.
CommonsChunkPlugin
First post a section of their own official website introduction:
The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.
Webpack-packed code is stored as chunks. The CommonsChunkplugin, however, takes the same modules from different chunks and places them in a common chunk. This public chunk only needs to be downloaded once, and all chunks can use it. And this part of the code can be placed in the cache, so that you do not need to download later (there is also an article about using Webpack to do cache, if you are interested). There’s also less code per chunk, so each load is faster.
How to use CommonsChunkplugin?
Common parameters:
1. Determine the parameters for generating chunk: name, Names, async
Name: string: indicates the name of the public chunk. If an existing chunk name is passed in, that chunk is used as a public chunk to hold the extracted common code. Otherwise, Webpack creates a new public chunk.
Names: string[]: The same as name, but passed in an array. It’s like doing a code cut for each element in the array.
Async: Boolean | string: the common code to extract a chunk, lazy loading is used to download, then when the incoming value to a string, the value will be used as lazy loading the chunk name. Currently, this is usually done with children (Entry chunks are loaded when the app is initialized, so adding async tags doesn’t make sense).
2. Decide on chunks: chunks, children, and deepChildren to be extracted
Chunks: string[]: Webpack will fetch common code from incoming chunks or, if not, from all entry chunks. Children: Boolean: when children(deepChildren) is not set, webpack extracts common code from entry chunk based on conditions. When children is set to true, Webpack extracts the code from the direct sub-chunks of the entry chunk. DeepChildren: Boolean: Same as children, but selects all sub-nodes of the common chunk.
3. Determine extraction conditions: minChunks
minChunks: number|infinity|function(module,count)->boolean: Passing a number or infinity(the default is 3) tells WebPack that the module will only be extracted if the number of module repeats is greater than or equal to that number. When the input is a function, all the modules in the eligible chunk will be passed into the function for calculation, and the modules that return true will be extracted to the target chunk.
Long winded a lot, to sum up:
- In webpack, there are two types of chunks: entry chunk and normal chunk. If you want to extract common chunks in normal chunk without setting them manually, set children(deepChildren) to true. Otherwise, the chunk is an Entry chunk. If you are not satisfied with the webpack categories, use chunks to manually specify the chunks to be selected.
- Set async to true if you want to do lazy loading of packaged public chunks.
- MinChunks are used to determine which modules to extract into the common chunk
Here are a few more examples:
case 1
Two entry apps and page1 use react, react-dom and classnames. We need to extract modules that appear twice or more into a common chunk vendor: App:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as axios from 'axios';
import * as classnames from 'classnames';
Copy the code
Page1:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as classnames from 'classnames';
Copy the code
Webpack configuration:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2,
}),
Copy the code
case 2
Continuing with the case1 example, we can see that the axios package is still mixed up with the app’s business code. Pull him out again:
new webpack.optimize.CommonsChunkPlugin({
name: 'axios',
chunks: ['app'],
minChunks: function(module) {
return/axios/.test(module.context); }}),Copy the code
Of course, this is for the purpose of writing examples of chunks, so you don’t have to do this twice in practice. Just type all the libraries in node_modules into vendor for the first fetch (minChunks: 1 is ok)
case 3
If the sub-chunk exists, here I choose to extract the sub-chunk into a new lazy chunk: App asynchronous reference Home, Topics, About:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as moment from 'axios';
import * as classnames from 'classnames';
const Home = () => import('./Home');
const Topics = () => import('./Topics');
const About = () => import('./About');
Copy the code
Home,Topic, and About all reference Mobx and moment
import * as React from 'react';
import * as moment from 'moment';
import * as mobx from 'mobx';
Copy the code
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor',
children: true,
minChunks: 2,
}),
Copy the code
As shown in the figure, it is equivalent to telling Webpack to scan the modules in the direct sub-chunks (Home, Topics, About) of app(Entry Chunk) and extract the modules that appear more than 2 times and put them into a lazy loading module named Vendor.
case 4
In addition to extracting common modules, the CommonsChunkPlugin is also very useful for front-end engineering code cutting. To make better use of the cache, suppose we have the following requirements:
-
Webpack Runtime (Entry Chunk) : As mentioned above, the Runtime code must be executed before any other code. And since the Runtime code changes frequently with module and chunk IDS, it is recommended to package it separately
-
Lib (Normal chunk): Lib contains basic libraries such as react, react-dom, and react-router that will not change.
-
Vendor (Normal Chunk): Vendor hosts a library of tools like Axios, Moment, and others that change occasionally
-
Normal Chunk: Changes at any time, a separate chunk
Direct configuration:
new webpack.optimize.CommonsChunkPlugin({
deepChildren: true,
async: 'async-vendor',
minChunks: function (module) {
return /node_modules/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return /node_modules/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "lib",
minChunks: function (module) {
return /react/.test(module.context);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
Copy the code
First packing: Extract the common module (MOBx, moment) from the direct sub-chunks (Home,Topics,About) of all Entry Chunks (app, page1) and put it into lazy loading chunk async-vendor.
Second packaging: Extract the modules in node_modules from all entry chunks (app, page1) and put them into chunk vendor. App, page1 now becomes normal chunk.
Third packaging: Extract modules with react paths from all entry chunks (vendor) and place them in chunk lib.
Fourth packaging: Create a manifest chunk without any modules (minChunks: Infinity). Since the MANIFEST is the only chunk of entry at this point, the Runtime code goes into the Manifest.
As shown, the business code is completely separated from the lib code, vendor tool code, and so on.
reference
CommonsChunkPlugin
Code Splitting
Vendor and code splitting in webpack 2
webpack: Unraveling CommonsChunkPlugin
webpack bits: Getting the most out of the CommonsChunkPlugin()
Added deepChildren support from ArcEglos’ pull request