# 性能优化 - 构建
- 构建 —— 开发阶段 —— 开发效率
- 传输 —— 打包后的 js 代码传输到浏览器的时间 ——总传输量、文件数量、浏览器缓存
- 运行 —— js 代码在浏览器端的运行速度 —— 代码质量 (尾递归优化等,永远不要过早关注性能)
# 减少模块解析
- 甚至不解析模块。
- 什么叫模块解析?AST抽象语法树分析,记录依赖报存到 dependencies 中,替换依赖函数。
- 哪些模块不用解析呢?模块中无其他依赖(不进行 AST 抽象语法树分析,一些已经打包好的第三方库,例如:jquery)
module: { noParse: /jquery/ }
# 优化 loader 性能
# 限制 loader 的使用范围
- babel-loader 转换 es6 的语法,但是某些库把本身就是低版本写的,不需要 babel-loader 处理,例如:lodash 。
- 通过
module.rules.exclude
和module.rules.include
排除掉或者仅仅支持哪些库进行配置。- 暴力写法,直接排除
node_modules
只管 src 目录下的代码。 - noParse 和 exclude 不冲突,因为模块解析不包含 loader 处理。
- 暴力写法,直接排除
# 缓存 loader 结果
- 代码内容不变,经过 loader 处理,结果不变。
- cache-loader 最后使用缓存 loader ,它最后执行的,怎么能实现后续使用缓存呢?
- pitch 过程 loader.pitch = (filePath) => {}
- 指定缓存的路径
# 开启多线程(大项目)
- thread-loader 会开启一个线程池,线程池中包含适量的线程。
- 放到 cache-loader 后面,因为主要是为了处理模块解析耗时问题。后续的 loader 都会放到新线程中处理。
- 用 webapck api 生成文件 —— 不在 webpack 主线程。
- 不同使用自定义的 plugin api , 例如:
mini-css-extact-plugin
提供的 plugin 会向 webpack 注入了新的 api ,这时候就会报错。 - 无法访问 webpack options 。
- 放 babel-loader 等。
测试几核的 cpu
const cpus = require('os').cpus;
console.log(cpus().length)
1
2
3
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
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
生成的文件是在构建期间,运行期间也无法改动文件,因此是无效的。