# 性能优化 - 构建

  1. 构建 —— 开发阶段 —— 开发效率
  2. 传输 —— 打包后的 js 代码传输到浏览器的时间 ——总传输量、文件数量、浏览器缓存
  3. 运行 —— js 代码在浏览器端的运行速度 —— 代码质量 (尾递归优化等,永远不要过早关注性能)

# 减少模块解析

  • 甚至不解析模块。
  • 什么叫模块解析?AST抽象语法树分析,记录依赖报存到 dependencies 中,替换依赖函数。
  • 哪些模块不用解析呢?模块中无其他依赖(不进行 AST 抽象语法树分析,一些已经打包好的第三方库,例如:jquery)
    • module: { noParse: /jquery/ }

# 优化 loader 性能

# 限制 loader 的使用范围

  • babel-loader 转换 es6 的语法,但是某些库把本身就是低版本写的,不需要 babel-loader 处理,例如:lodash 。
  • 通过 module.rules.excludemodule.rules.include 排除掉或者仅仅支持哪些库进行配置。
    • 暴力写法,直接排除 node_modules 只管 src 目录下的代码。
    • noParse 和 exclude 不冲突,因为模块解析不包含 loader 处理。

# 缓存 loader 结果

  • 代码内容不变,经过 loader 处理,结果不变。
  • cache-loader 最后使用缓存 loader ,它最后执行的,怎么能实现后续使用缓存呢?
    • pitch 过程 loader.pitch = (filePath) => {}
  • 指定缓存的路径

# 开启多线程(大项目)

  • thread-loader 会开启一个线程池,线程池中包含适量的线程。
  • 放到 cache-loader 后面,因为主要是为了处理模块解析耗时问题。后续的 loader 都会放到新线程中处理。
    1. 用 webapck api 生成文件 —— 不在 webpack 主线程。
    2. 不同使用自定义的 plugin api , 例如: mini-css-extact-plugin 提供的 plugin 会向 webpack 注入了新的 api ,这时候就会报错。
    3. 无法访问 webpack options 。
    4. 放 babel-loader 等。

测试几核的 cpu

const cpus = require('os').cpus;

console.log(cpus().length)
1
2
3

# 热替换(HMR)

hot module replacement 热替换并不能降低构建时间(可能还会稍微增加),但可以降低代码改动到效果呈现的时间。

当使用webpack-dev-server时,考虑代码改动到效果呈现的过程

代码改动

而使用了热替换后,流程发生了变化:

热替换

# 使用和原理

module.exports = {
  devServer: {
    hot: true,
  },
  plugins: [
    // 可选
    new webpack.HotModuleReplacementPlugin()
  ]
}

// 判断是否开启热更新
if (module.hot) {
  module.hot.accept(); // 接受热更新
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • webpack-dev-server 会向打包结果中注入 module.hot 属性,重新打包后,会调用 location.reload() 来刷新页面,但是如果运行了 module.hot.accept ,让 webpack-dev-server 通过 socket 管道,把服务器内容发送到浏览器。
  • 热替换
  • 将结果交给 HotModuleReplacementPlugin 注入的代码执行,插件会覆盖原始代码,让代码重新执行。

# 样式热替换

  • style-loader ,因为热替换发生时,只会简单地重新运行模块代码,因此 style-loader 的代码一运行,就会重新设置 style 中样式,但是 mini-css-extract-plugin 生成的文件是在构建期间,运行期间也无法改动文件,因此是无效的。
更新时间: 2022年8月21日星期日 19:33