1. Why code separation
In single-page or multi-page applications, code separation can optimize performance.
For example, splitting asynchronously loaded code into a separate chunk and loading it on demand when it needs to be called (for example, at Click) can reduce the size of the first screen of code, thus increasing the first screen load speed.
In addition, in our project, we may use a lot of third party libraries (such as LoDash, RXJS, etc.), and the code of these third party dependencies usually changes very little. Therefore, it is a good idea to separate the third party dependencies into a package and include hash in the package name (webPack can easily do this). The advantage of this is that it can be combined with browser HTTP caching mechanisms, such as max-age, to achieve a long cache of related resource bundles, thus optimizing performance.
Common scenarios for code splitting are:
- Separate business code from third-party dependencies
- Separate first – and asynchronously loaded code
- Separate the business code from the common code of the business
2. Install dependencies
Index.html is automatically generated by html-webpack-plugin
npm install -D html-webpack-plugin
npm install -D webpack // html-webpack-plugin relies on webpack
npm install --save axios lodash
Copy the code
3. Directory structure
// '--' represents directory, '-' represents file
--demo09
--src
-app.js
-async-module1.js
-async-module2.js
-module.js
-index.html
-webpack.config.js
Copy the code
src/async-module1.js
export const data = 'this is async module1';
Copy the code
src/async-module2.js
export const data = 'this is async module2';
Copy the code
src/module.js
export const sayHello1 = (a)= > {
console.log('Hi I want to say hello1');
}
export const sayHello2 = (a)= > {
console.log('Hi I want to say hello2');
}
export const sayHello3 = (a)= > {
console.log('Hi I want to say hello3');
}
Copy the code
src/app.js
import { sayHello1, sayHello2, sayHello3 } from './module';
sayHello1();
sayHello2();
sayHello3();
// Load async-module1 asynchronously
setTimeout((a)= > {
require.ensure(
[],
function () {
const asyncModule = require("./async-module1");
console.log(asyncModule.data);
},
"module1"
);
}, 3000);
// Load async-module2 asynchronously
setTimeout((a)= > {
require.ensure(
[],
function () {
const asyncModule2 = require("./async-module2");
console.log(asyncModule2.data);
},
"module2"
);
}, 3000);
// Reference third-party libraries
// https://github.com/lodash/lodash
import * as _ from "lodash";
// https://github.com/axios/axios
import * as axios from "axios";
console.log(_);
console.log(axios);
Copy the code
3. Configure rules for packaging third-party libraries
SplitChunks with webpack4 is easy to do.
See my article Demo08 on SplitChunksPlugin for details on how to use the various parameters of splitChunks
splitChunks: {
cacheGroups: {
vendors: {
chunks: "all".// Use all mode
test: /[\\/]node_modules[\\/]/.// Matches the module under node_modules
name: "vendors".// Package name, the final name should be combined with output chunkFilename
minChunks: 1.minSize: 30000.priority: 10 // Set the priority}}}Copy the code
4. Configure rules for packaging asynchronous loading packages
Package asynchronous load packages
splitChunks: {
cacheGroups: {
async: {
chunks: "async".minChunks: 1.// The minimum number of times a code block has been referenced
maxInitialRequests: 3.// Set the maximum number of requests
minSize: 0.// Set the minimum size of each chunk (default 30000) to 0 for testing purposes
automaticNameDelimiter: '~'.priority: 9}}},Copy the code
5. Complete WebPack configuration file
const path = require("path");
module.exports = {
mode: 'development'.In production mode, [name] is converted to 0, 1, 2...
entry: {
app: "./src/app.js",},output: {
publicPath: __dirname + "/dist/".// References to packaged resource files will be based on this path
path: path.resolve(__dirname, "dist"), // The packaged output directory
filename: "[name].[chunkhash].bundle.js".// Each package contains chunkhash
chunkFilename: "[id].[chunkhash].chunk.js"
},
optimization: {
runtimeChunk: "single".splitChunks: {
cacheGroups: {
async: {
chunks: "async".minChunks: 1.// The minimum number of times a code block has been referenced
maxInitialRequests: 3.// Set the maximum number of requests
minSize: 0.// Set the minimum size of each chunk (default 30000) to 0 for testing purposes
automaticNameDelimiter: '~'.priority: 9
},
vendors: {
chunks: "all".// Use all mode
test: /[\\/]node_modules[\\/]/.// Matches the module under node_modules
name: "vendors".// Package name, the final name should be combined with output chunkFilename
minChunks: 1.minSize: 30000.priority: 10 // Set the priority}}}}};Copy the code
5. Run the package command
(You have global Webpack and webPack-CLI installed by default)
webpack
Copy the code
After successful packaging, the output is in the dist directory of Demo09
(Note that “mode” is set to “development”)
app226.A343cb53e0a689358. The chunk. Js (app) main moduleasync~module187.d116fd41640c30a6b2.chunk.js (async- module1 module)async~module265866.f4d15253512c981.chunk (async- Module2 Module) Runtime.4e6De616bd3030f8bff8. Bundle. Js (webpack runtime modules) vendors. A83c085b3a7ac03b1b47. The chunk. Js (third party relies on module)Copy the code
6. Modify the program code to verify the packaging results
You can change the app. The js code, such as run a webpack command again, you will find that a third party based on module package name has not been changed: vendors. A83c085b3a7ac03b1b47. The chunk. Js.
Run dist/index.html in a browser and open the console to see the effect of asynchronously loading the module.
(note: the runtime. XXXXXXXX. Bundle. Js module contains references logic for induction load module, in addition, the asynchronous loading reference relative path from the output – > publicPath configuration)
7. Source address
Demo code address: github.com/SimpleCodeC…
Warehouse code address (and directory): github.com/SimpleCodeC…