背景
前端小伙伴都知道,为了降低包大小,经常会把依赖的前端模块独立打包,比如把 vue
、vue-router 打到一个单独的包
vendor` 中。另外,常会将存在多个路由的复杂页面的每个页面都单独打一个包,只有访问某个页面的时候,再去下载该页面的js包,以此来加快首页的渲染。
无论是 react
还是 vue
都提供了完善的工具,帮我们屏蔽了繁琐的配置工作。当我们对代码进行构建时,已经自动帮我们完成了代码的拆分工作。
所以,很多小伙伴并不知道背后到底发生了什么事。至于为什么这么拆分,到底如何控制代码的拆分,更是一头雾水了。
问题测验
讲解开始之前,大家先看一个问题。如果你已经知道问题的答案,而且明白为什么,就不必往下阅读了。如果不知道答案或者知道答案,但不知道原因。那么,强烈建议阅读本文。
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: { app: "./src/index.js" },
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist")
},
optimization: {
splitChunks: {
chunks: "all"
}
},
plugins: [
new HtmlWebpackPlugin()
]
};
// index.js
import "vue"
import(/*webpackChunkName: 'a' */ "./a");
import(/*webpackChunkName: 'b' */ "./b");
// a.js
import "vue-router";
import "./someModule"; // 模块大小大于30kb
// b.js
import "vuex";
import "./someModule"; // 模块大小大于30kb
// someModule.js
// 该模块大小超过30kb
// ...
三种代码拆分方式
webpack 中以下三种常见的代码分割方式:
入口起点:使用
entry
配置手动地分离代码。动态导入:通过模块的内联函数调用来分离代码。
防止重复:使用
splitChunks
去重和分离 chunk。第一种方式,很简单,只需要在entry
里配置多个入口即可:
entry: { app: "./index.js", app1: "./index1.js" }
第二种方式,就是在代码中自动将使用 import()
加载的模块分离成独立的包:
//...
import("./a");
//...
第三种方式,是使用 splitChunks
插件,配置分离规则,然后 webpack
自动将满足规则的 chunk
分离。一切都是自动完成的。
前两种拆分方式,很容易理解。本文主要针对第三种方式进行讨论。
splitChunks 默认配置
splitChunks: {
// 表示选择哪些 chunks 进行分割,可选值有:async,initial和all
chunks: "async",
// 表示新分离出的chunk必须大于等于minSize,默认为30000,约30kb。
minSize: 30000,
// 表示一个模块至少应被minChunks个chunk所包含才能分割。默认为1。
min