一、什么是code split
一般我们会在入口文件main.js中引入了第三方库,假设我们引入的是moment,再假设他有2M;同时我们编写的几万行的业务代码有1M,那此时我们运行npm run build打包,最终出来的是main.js大小是3M,那就意味着用户首次打开index.html需要等待一个3M的js资源加载完成之后才会去执行文件里面的逻辑,进而把页面渲染出来。那么这将带打来几个问题:
- 打包文件会很大,首屏加载时间过长
- 资源重复加载:我们每次更新我们的业务逻辑代码,这将意味着每次重新访问页面都将需要加载这3M的js资源。但我们的第三方库一般情况下是不会改变的,是不需要每次都重新加载此资源
所以我们需要对代码进行分开打包,也就是我们的code split
二、如果进行code split
演示案例的准备工作
- 创建相应的目录并安装webpack
mkdir code-split
cd demo-01
npm init -y
npm install webpack webpack-cli --save-dev
webpack.config.js
// 基本配置
const path = require('path');
module.exports = {
mode: "production",
entry: './src/main.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
- 其他js文件随心情随便写点js代码
function add(x, y) {
retur x + y
}
console.log(add(1, 2))
- 执行命令
npx webpack打包
1. entry
- 单入口 webpack.config.js
// 基本配置
const path = require('path');
module.exports = {
mode: "production",
entry: './src/main.js',
output: {
filename: '[name].chunk.[contenthash:10].js', // 修改输出文件的命名规则,便于我们区分
path: path.resolve(__dirname, 'dist'),
},
};
在main.js中引入test.js
+ import { mult } from "./test.js"
function add(x, y) {
return x + y
}
console.log(add(1, 2))
+ console.log(mult)
运行npx webpack打包,将会生成一个chunk文件
- 多入口
其他不变仅修改
webpack.config.js中的entry配置:
// 基本配置
const path = require('path');
module.exports = {
mode: "production",
// entry: './src/main.js',
entry: {
main: './src/main.js',
test: './src/test.js'
},
output: {
filename: '[name].chunk.[contenthash:10].js',
path: path.resolve(__dirname, 'dist'),
}
};
运行npx webpack打包,将会生成两个chunk文件
2.SplitChunksPlugin
// webpack5 默认配置
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'async',// 指明要分割的插件类型, async:异步插件(动态导入),inital:同步插件,all:全部类型
minSize: 20000,// 文件最小大小,单位bite;即超过minSize有可能被分割;
minRemainingSize: 0,// webpack5新属性,防止0尺寸的chunk
maxSize: 0,
minChunks: 1, // 模块的最小引用次数,如果引用次数低于这个值,将不会被优化
maxAsyncRequests: 30,// 设置async chunks的最大并行请求数 webpack4,5区别较大
maxInitialRequests: 30,// 设置initial chunks的最大并行请求数 webpack4,5区别较大
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: { // 缓存组,自定义拆包规则在此定义
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
// ...
};
// webpack4 默认配置
module.exports = {
// ...
splitChunks: {
chunks: "async", // initial:直接引入的模块 | async:按需引入的模块 | all:all in
minSize: 20000, // 最小包体积,这里的单位是byte,超过这个大小的包会被splitChunks优化
minChunks: 1, // 模块的最小引用次数,如果引用次数低于这个值,将不会被优化
maxAsyncRequests: 5, // 设置async chunks的最大并行请求数
maxInitialRequests: 3, // 设置initial chunks的最大并行请求数
automaticNameDelimiter: '~', // 产出chunks的文件名分割符
name: true, // true:根据提取chunk的名字自动生成,false:根据缓存组IdHint生成,string:生成文件命即为这个string
cacheGroups: { // 缓存组,自定义拆包规则在此定义
vendors: { // 默认配置,node_modules的chunk
test: /[\/]node_modules[\/]/,
priority: -10
},
default: { //业务代码的chunk
minChunks: 2,
priority: -20,
reuseExistingChunk: true //复用已存在的chunks
}
}
}
// ...
};
演示案例:多入口文件打包
webpack.config.js
// 增加optimization配置
const path = require('path');
module.exports = {
mode: "production",
// entry: './src/main.js',
entry: {
main: './src/main.js',
test: './src/test.js'
},
output: {
filename: '[name].chunk.[contenthash:10].js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
};
- 修改
main.js,在其中引入vue,先npm install vue
import { mult } from "./test.js"
import { VueElement } from "Vue"
function add(x, y) {
return x + y
}
console.log(add)
console.log(mult)
console.log(VueElement)
- 运行
npx webpack打包,将会生成三个chunk文件
如果注释掉webpack.config.js中的optimization,将只会生成两个chunk文件
如果存在两个src/*.js同时引用一个第三方库,将只会打包一次chunk文件
修改test.js代码,使其引入vue.js;main.js不变
import { VueElement } from "Vue"
function mult(x, y) {
return x * y
}
console.log(mult)
console.log(VueElement)
export {
mult
}
3. 通过js代码,动态导入
修改main.js中的代码,使其动态引入test.js;
import { VueElement } from "Vue"
function add(x, y) {
return x + y
}
console.log(add)
console.log(VueElement)
// 将单独打包
import(/* webpackChunkName: 'test' */"./test.js").then((mult) => console.log(mult)).catch(err => console.log(err))
修改webpack.config.js中的配置,采用单页面模式并关闭optimization;
// 基本配置
const path = require('path');
module.exports = {
mode: "production",
entry: './src/main.js',
output: {
filename: '[name].chunk.[contenthash:10].js',
path: path.resolve(__dirname, 'dist'),
}
};
运行npx webpack打包,将会生成两个chunk文件