跳到主要内容

代码分割

为什么CSS 文件分离出来,而不是直接一起打包在 JS 中?

  • 主要的原因是我们希望更好地利用缓存

1、假设静态资源都打包成一个js文件,加载页面时虽然只需要加载一个 JS 文件,但是我们的代码一旦改变了,用户访问新的页面时就需要重新加载一个新的 JS 文件。有些情况下,我们只是单独修改了样式,这样也要重新加载整个应用的 JS 文件,相当不划算

2、还有一种情况是我们有多个页面,它们都可以共用一部分样式(这是很常见的,CSS Reset、基础组件样式等基本都是跨页面通用),如果每个页面都单独打包一个 JS 文件,那么每次访问页面都会重复加载原本可以共享的那些 CSS 代码

如果分离开来,第二个页面就有了 CSS 文件的缓存,访问速度自然会加快。虽然对第一个页面来说多了一个请求,但是对随后的页面来说,缓存带来的速度提升相对更加可观

  • optimization.splitChunks

    • 公共引用的模块(库)帮单独提出来做下代码分割
    • 自动生成了一个verdor~main.js文件
    js
    optimization:{
    splitChunks:{
    chunks:"all"//所有的 chunks 代码公共的部分分离出来成为一个单独的文件
    }
    }

我们需要在 HTML 中引用两个构建出来的 JS 文件,并且 commons.js 需要在入口代码之前。下面是个简单的例子:

text
<script src="commons.js" charset="utf-8"></script>
<script src="entry.bundle.js" charset="utf-8"></script>

使用了 html-webpack-plugin,那么对应需要的 JS 文件都会在 HTML 文件中正确引用

理解chunks​

splitChunks的作用

  • 可以提取公共模块
  • 将第三方包进行拆分,生成vendor

chunks 用以告诉 splitChunks 的作用对象,其可选值有 async、 initial 和 all。默认值是 async,也就是默认只选取异步加载的chunk进行代码拆分

  • chunks 值为all 时,会比较强大,一般设置为all即可,处理范围包括了初始chunk和异步chunk两种场景

webpac高效拆包​

将公共使用的第三方类库配置为公共的部分

不应该由 webpack 自己去判断处理。因为公共的第三方类库通常升级频率相对低一些,这样可以避免因公共 chunk 的频繁变更而导致缓存失效

  • 显示指定哪些类库作为公共部分
js
module.exports = {
entry: {
vendor: ["react", "lodash", "vue", ...], // 指定公共使用的第三方类库
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: "initial",
test: "vendor",
name: "vendor", // 使用 vendor 入口作为公共部分
enforce: true,
},
},
},
},
// ... 其他配置
}

或者

  • 利用test属性 正则 来做模块路径的匹配
js
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /react|angluar|lodash/, // 直接使用 test 来做路径匹配
chunks: "initial",
name: "vendor",
enforce: true,
},
},
},
},
}

或者

  • 所有在 node_modules 下的模块,即作为依赖安装的,都作为公共部分。你可以针对项目情况,选择最合适的做法。
js
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: "initial",
test: path.resolve(__dirname, "node_modules") // 路径在 node_modules 目录下的都作为公共部分
name: "vendor", // 使用 vendor 入口作为公共部分
enforce: true,
},
},
},
},
}

上述

第一种做法是显示指定哪些类库作为公共部分

第二种做法实现的功能差不多,只是利用了 test 来做模块路径的匹配

第三种做法是把所有在 node_modules 下的模块,即作为依赖安装的,都作为公共部分。你可以针对项目情况,选择最合适的做法。

把第三方包打成vendor怎么操作?​

  • 通过optimization的splitChunks属性配置
    • 可以将第三方库的代码提取到一个单独的Vendor文件中。
  • 需要在入口文件enrty配置指定 第三方库入口
js
module.exports = {
entry: {
app: './src/index.js', // 主应用程序入口
vendor: ['react', 'react-dom', 'jquery'] // 第三方库入口
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: "initial",
test: path.resolve(__dirname, "node_modules") // 路径在 node_modules 目录下的都作为公共部分
name: "vendor", // 使用 vendor 入口作为公共部分
enforce: true,
minChunks:1
},
},
},
},
}

好处​

更好地利用缓存 【浏览器缓存机制】 --> 性能优化

  • 因为第三方库通常不会经常变化,可以利用缓存,减少了初始加载时间