webpack - 性能优化
优化
使用 include 或者 exclude 配置,避免重复打包
- 引入的一些插件、类库都是被打包过了的,用babel编译的时候,需要配置一下,给已经编译过的语法剔除掉,这样就能减少打包时间
- 比如在项目中引入jq插件,取用jq时,npm搜索会先从当前目录的node_modules中找,找不到,就往上一级目录node_modules,一直往上找到磁盘。如果都没有,才报错
- 找到 node_modules 包之后找到 package.json 文件,在文件中找到 入口文件去加载,加载后发现已经是编译过的文件了
1 | { |
利用缓存减少打包时间
1 | { |
- 一些公用不改动的库可以使用,还可
cache-loader
在开销较大的loader前使用即可
1 | { |
合理使用plugin,减少打包时间和体积
尽量选择官方推荐的plugin
使用插件避免引用无用模块代码
- 比如:使用moment库时, 打包默认会把整个库引入进来,这样导致库非常大,可以使用
igonrePlugin
忽略插件的某个无用文件夹,这样就可以减少打包体积 - 比如:使用压缩css的OptimizeCSSAssetsPlugin时 只需在生产环境下对代码做压缩,在开发环境下就不需要这个插件,缩短压缩时间
- 比如:使用moment库时, 打包默认会把整个库引入进来,这样导致库非常大,可以使用
合理配置relosve,防止减慢打包时间
- 引入es6模块时,不用写文件后缀也能引用进来,这就是 webpack 的 relosve 配置参数
1 | resolve:{ |
- 比如jpg、css、png等,由于不写后缀,在查找的时候,会给
extensions
数组中所有元素遍历完找不到才会报错,增加了查找时间,所以要合理利用
启用多线程打包
- 使用happy、推荐使用
thread-loader
、ParallelUglifyPlugin
- 项目较大推荐使用,项目较小打包开启多线程会有额外的性能开销,反而将时间拖慢了
happypack
- 本身就是对node开启一个多进程打包
1 | const HappyPack = require('happypack') |
thread-loader
thread-loader
放置在其他loader之前,之后的loader就会在一个单独的worker池中运行,并且还支持定义配置,方便性能优化
1 | { |
ParallelUglifyPlugin
- 压缩JS 需要先将代码解析成AST语法树,根据复杂规则分析和处理AST,最后将AST还原成JS,这个过程涉及大量计算,因此比较耗时
1 | const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin') |
开发中使用热更新替换自动跟新
- 项目体积过大,每次改完代码都要刷新页面
1 | const webpack = require('webpack') |
使用 DllPlugin 插件,提高打包时间
使用比较稳定的库时,比如:react、vue、jq 几个月都不会更新,就不需要重复打包,只需要打包一次,下次打包引用即可
编写dll的配置文件
1 | const path = require('path') |
- 在webpack中配置映射关系,防止打包时再次引用npm包
1 | const DllReferencePlugin = require('webpack/lib/DllReferencePlugin') |
- html中引用打包的公用模块,因为在配置
DllReferencePlugin
时,底层其实时在实行的时候在window中寻找这个包,所以必须引入进来打包后的这个文件,相应的这个公用模块也会在window下挂一个全局变量,引入方式可以使用AddAssetHtmlWebpackPlugin
插件引入,也可以手动引入
打包时合理使用hash,如果没改动的文件 命中缓存
1 | output:{ |
提取公用代码,代码分割
- 提取多个模块的公共代码,只需要打包一次,实现更小的代码体积
1 | optimization:{ |
使用 tree-shaking 去除无用代码减少代码体积
1 | // a.js |
TerserPlugin.terserMinify
替换 esbuild
方式
- 默认使用的是
TerserPlugin.terserMinify
1 | `npm install esbuild - D` |