One, foreword
In the previous article, I talked about packaging configurations in different modes. In this article, I will talk about Code Splitting.
// index.js
import _ from 'lodash';
let element = document.createElement('div');
element.innerHTML = _.join(['Hello'.'webpack'].' ');
document.body.appendChild(element);
Copy the code
If we look at the code above, we can see that loDash was introduced synchronously at the beginning, which is fine, but once the index.js file is large, as soon as the code in index.js changes, the whole index.js will be reloaded and LoDash will be reintroduced. In short, every time you modify index.js, it causes loDash to be introduced, which is a waste.
After packing, open your browser to see the result:
2. Entry configuration
Write the fixed reuse code (in the case of LoDash) in a JS file and place it in the Entry configuration.
Note the order of lodash and index.
// lodash.js
import _ from 'lodash';
window. _ = _;// index.js (main file)
let element = document.createElement('div');
element.innerHTML = _.join(['Hello'.'webpack'].' ');
document.body.appendChild(element);
Copy the code
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development'.entry: {
lodash: './src/lodash.js'.// Note the order, lodash first
index: './src/index.js' // So that the index.js code can use Lodash
},
output: {
filename: '[name].js'.path: path.resolve(__dirname, 'dist'),}}Copy the code
Thus, main.js is split into lodash.js and index.js.
- When the page is first loaded, a copy of Lodash.js is loaded (1.5MB) and a copy of index.js (44.2kB).
- When changing business code, only index.js (44.2kB) is reloaded, while the lodash.js copy (1.5MB) is cached by the browser and not reloaded.
This is one way to manually separate the code, but it’s still cumbersome.
Let’s restore the entry configuration to its original entry: ‘./ SRC /index.js’
Third, Code Splitting
1. Default Settings
Webpack provides a code separation feature, which by default separates asynchronous code as follows:
module.exports = {
/ /...
optimization: {
splitChunks: {
chunks: 'async'.// async or async
minSize: 20000.// If the module size is smaller than this value, it will not be split by 20K
minRemainingSize: 0.// The minimum size that can be saved is 0 in development mode and equal to minSize in other cases
minChunks: 1.// If the module is referenced less than this value, it will not be split
maxAsyncRequests: 30.// Asynchronous module, the maximum number of times to be loaded at one time
maxInitialRequests: 30.// The maximum number of times an entry module is loaded
enforceSizeThreshold: 50000.// The size threshold for mandatory segmentation is 50K
cacheGroups: { / / cache group
// Package third-party libraries
defaultVendors: {
test: /[\\/]node_modules[\\/]/.// Re matches third-party library files
priority: -10./ / priority
reuseExistingChunk: true.// If a module is already packaged, it will not be packaged either
},
// Package the public module
default: {
minChunks: 2.// The package must be referenced by more than two modules
priority: -20./ / priority
reuseExistingChunk: true.// If a module is already packaged, it will not be packaged either},},},},};Copy the code
2. Synchronization code processing
But apparently it is powerless to synchronized code, so we set like this: the optimization. The splitChunks. The value is set to all chunks, it says: Code separation happens both synchronous and asynchronous, but be aware that if your shared modules are not part of a third-party library (that is, not found in node_modules) and are your own code modules, they will be packaged with the default configuration under cacheGroups. If it is a third-party library, it is packaged according to the defaultVendors configuration under cacheGroups.
module.exports = {
/ /...
optimization: {
splitChunks: {
chunks: 'all'.// Synchronous or asynchronous
minSize: 100.// Set your own minimum split size
cacheGroups: { / / cache group
// Package third-party libraries
defaultVendors: {
test: /[\\/]node_modules[\\/]/.// Re matches third-party library files
priority: -10./ / priority
reuseExistingChunk: true.// If a module is already packaged, it will not be packaged either
filename: 'vendors.js' // The packaged file name
},
// Package the public module
default: {
minChunks: 2.// Only when referenced by more than two modules will it be packaged (can be removed)
priority: -20./ / priority
reuseExistingChunk: true.// If a module is already packaged, it will not be packaged either
filename: 'common.js' // The packaged file name},},},},};Copy the code
In this way, the business code is separated from the third-party library or its own module code, and the effect is the same as if we had split the code manually.
If, after packing, you find that your modules are not broken up, your module size does not meet the requirements for splitting (minSize), or does not meet the requirements for caching (minChunks)…
3. Processing of asynchronous code
Going back to the first item above, you can see that for asynchronous code, separation of asynchronous code is turned on by default.
So, we don’t need to do anything special, it will help you separate.
Code introduced dynamically (import()) is typically asynchronous code that generates a chunk after packaging:
// index.js
function getComponent() {
return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _}) = > {
let element = document.createElement('div');
element.innerHTML = _.join(['Hello'.'webpack'].' ');
return element;
});
}
// async function getComponent() {
// const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash');
// let element = document.createElement('div');
// element.innerHTML = _.join(['Hello', 'webpack'], ' ');
// return element;
// }
document.addEventListener('click'.() = > {
getComponent().then(element= > {
document.body.appendChild(element);
});
});
Copy the code
Note: /* webpackChunkName: “lodash” */ is a magic comment that allows you to customize the name of the chunk that is separated. Chunk is the code that is separated.
This dynamically imported code is not imported when it is first loaded. (At this point, lodash.js has not been introduced)
Lodash.js is only introduced when the event that triggers the response (the page clicked, triggering the getComponent function) is triggered.
So, to some extent, dynamic import is better than synchronous import, which is why WebPack separates asynchronous code by default. Also, with asynchronous code, code utilization is improved.
4. Preload or obtain modules
Prefetch: After the browser has loaded the necessary resources, it will fetch the resources that may be needed when it is idle.
Preload: Preloads resources that may be needed for the current page, requested in parallel with the necessary resources.
import(/* webpackPrefetch: true */ './assets/js/click')
Copy the code
As shown, it pre-fetches the async module annotated with magic when the network is idle after all the necessary resources have been loaded.
As you can see, the label changes accordingly.
5. CSS code separation
CSS can also be separated from the main file and added to the STYLE tag of the HTML when packaged by default.
If the CSS code has many lines, embedding it directly into the HTML file is not appropriate. We want it to be inserted into the head tag as a link tag, which is the form of an external import CSS file.
First install the plug-in:
npm install --save-dev mini-css-extract-plugin
Copy the code
Note: It works with CSS-Loader.
// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [{test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],},],},};Copy the code
Note: in addition to the introduction and configuration to the plugin, remember to ‘style – loader’ delete, add to MiniCssExtractPlugin loader.
After the package:
The style tag is gone, instead of the link tag introduced into the CSS.
summary
- Code separation: Separate duplicate code from the packaged final main.js file to avoid reloading and wasting performance.
- By default, only asynchronous code is separated; synchronous code needs to be set up manually.
- Import () is a dynamically imported syntax that Webpack will isolate for you as soon as you use it.
- Some asynchronous code that does not interfere globally can be prefetched or preloaded.
- CSS code separation: mini-CSS-extract-plugin
- What is Chunk? See here: juejin.cn/post/700652…