优化目标
- 降低打包体积
- 提升打包速度
两个目标第一个目标优先度是大于第二个的,最理想的情况是两者取得一个平衡点。
分析工具
(1) 速度: speed-measure-webpack-plugin
(2) 体积: webpack-bundle-analyzer
降低体积
Tree shaking
Tree shaking会通过静态分析代码,没有被用到的代码会被清掉。只支持ESM模式,因为commonjs模式会存在动态引入问题,Tree shaking需要在静态编译阶段处理。
webpack 4.x production mode默认开启
Scope Hoisting
Webpack会将模块包裹成模块初始化函数,模块越多体积越大。实际上有一些只被引用一次的模块可以打包进被引用模块的初始化函数中,节省掉模块初始化函数的包裹代码。这个优化就是Scope Hoisting。
webpack 4.x production mode默认开启
清除无用的css
purgecss-webpack-plugin, 原理是记录文件里面用到的样式名称,消除没有用到的。
图片压缩
image-webpack-loader
代码分割
(1)开启optimization.splitChunks
(2)使用动态加载import非首屏页面
JS代码压缩
在optimization中选择开启minimize:true
,还可以在minimizer
中配置相应的压缩插件:
(1) UglyJS
(2) terser-webpack-plugin
CSS代码压缩
使用MiniCssExtractPlugin
插件来压缩css文件,在Plugin配置好filename
和chunkFilename
之后,还要在loader中添加。要注意这个插件不能和style-loader
共用:1
2
3
4
5
6
7
8
9{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
}
使用动态polyfill
(1) 默认preset-env
只包含了语法的编译,例如箭头函数,const
,let
等,没有包含的一些API和函数方法,例如fetch
,Proxy
,Array.prototype.includes
等。可以通过配置preset-env
中的useBuiltIns: "usage"
启动按需引入,还需要配置browser
和corejs。
(2) 可以使用polyfill service
,会通过传过去的userAgent来返回对应的polyfill
文件
moment优化
(1) 可以使用IgnorePlugin:1
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
将所有语言包排除,然后再在用到moment的地方按需引入语言包:1
2
3
4const moment = require('moment');
require('moment/locale/ja');
moment.locale('ja')
(2) 使用ContextReplacementPlugin:1
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /ja|it/),
提升打包速度
使用更高版本的Webpack和node.js
Webpack 4.x比较3.x有如下的改动:
- 使用了更多的ES6语法优化,例如
for of
替换了forEach
,使用了includes
替换了indexOf
,使用了Map
和Set
来替换了Object
。 - 使用了md4哈希算法替换md5.
- loader可以直接传递AST给webpack,减少解析时间。
- 使用字符串方法替代正则表达式。
缩小构建的目标
通过配置resolve下面的几项:
extension - 后缀
modules - 搜索代码的文件夹
mainField - 项目的入口文件
alias - 别名
通过配置上面几项减少搜索带来的时间损耗,
babel-loader要exclude掉node_modules
等不需要的模块
并行构建/压缩
(1) Terser 压缩JS代码,开启并行模式。parallel=true
(2) HappyPack / thread-loader 并行解析。
利用缓存提升二次构建速度
(1) babel-loader?cacheDirectory=true
(2) cache-loader / hard-source-webpack-plugin
(3) terser-webpack-plugin开启缓存
dll分离第三方库
通过配置dllPlugin, 打包第三方库生成 *.dll.js和manifest.json文件,项目中配置DllReferencePlugin,打包的时候不再需要编译这些第三方库。注意,如果是支持按需引入或者非共用的库就不需要使用dll打包了,例如antd
,lodash
等。