前端开发体验提升-webpack打包速度优化
本篇主题是:webpack打包速度优化
准备分2步:
- 如何发现打包速度慢?(精确到哪个plugin慢,哪个loader慢)
- 如何解决慢的问题?
进入正题
如何发现打包速度慢?(精确到哪个plugin慢,哪个loader慢)
安装插件:speed-measure-webpack-plugin: https://www.npmjs.com/package/speed-measure-webpack-plugin
- 注:webpack5以上,可能会有问题
配置speed-measure-webpack-plugin的方法:
// 修改你的 webpack 配置
// 把以下这种对象
const webpackConfig = {
entry: '',
output: '',
plugins: [new MyPlugin(), new MyOtherPlugin()],
};
// 写成以下这种
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const webpackConfig = smp.wrap({
entry: '',
output: '',
plugins: [new MyPlugin(), new MyOtherPlugin()],
});
npm run build 后,效果如下
可以看到对应plugin和loader的耗时
知道了哪些地方慢之后,开始想办法解决慢的地方
如何解决慢的问题?
首先把官网推荐的优化操作,先给弄下来
(有些优化操作 新版本webpack已经内置了):https://webpack.docschina.org/guides/build-performance/#babel
整理出几个要操作的小点:
- 使用最新的版本(新版会有性能优化)
- 比如 用最新版的:webpack,node,各种loader和plugin
- 通过使用 include 字段,仅将 loader 应用在实际需要将其转换的模块: ```javascript const path = require(‘path’);
module.exports = { //… module: { rules: [ { test: /.js$/, include: path.resolve(__dirname, ‘src’), // 避免去扫描 node_modules loader: ‘babel-loader’, }, ], }, };
3. Devtool的sourceMap
- 用于生产(正式)环境中:(none)(或省略 devtool 选项) - 不生成 source map (减小体积)
- 正式环境也可以无害的使用sourceMap:博主的姊妹篇https://juejin.cn/post/6956047151843508232
- 用于开发(dev)环境中:推荐 eval-source-map
<br />基本的通用方案弄完后,是否就结束了? - 还没结束,还有优化空间,往下看
<a name="Y7Ti8"></a>
### 分析问题:哪些能优化?哪些动不了?
排除法,先看看哪些动不了?(此分析案例是vue工程,react工程也可以类似这么分析)
- 一般稳定的第三方loader或webpack官方插件,本身就已经做了优化,想动源码改造的话,成本过高,收益不明显。几乎可以忽略,比如:vue-loader,css-loader,sass-loader,less-loader等
除了“基本的开发标配”后,需开发者自己在去检查,项目内是否用了什么会耗时的插件。
举例:以博主接手的老公司项目来说,用上面讲的speed-measure-webpack-plugin插件,分析出能够操作的耗时项(一般是开发者自己额外添加的loader或plugin)
<a name="B5j1m"></a>
#### 优化1
检测到<br />`_image-webpack-loader@4.6.0@image-webpack-loader took 12.081 secs`
- image-webpack-loader:耗时12s。(其余的均为基本插件和loader,优化空间很小)
- 了解到image-webpack-loader的作用是压缩图片,并且每次打包都会重新压缩图片,太费时间。所以可以考虑,所有图片一次性压缩好(可以用https://tinypng.com/ ),然后在这个loader去掉
**打包速度优化效果: 30s -> 20s左右**
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6c7952fdf2d049f29abd24a5b8d28e49~tplv-k3u1fbpfcp-watermark.image#id=FHWCc&originHeight=104&originWidth=530&originalType=binary&status=done&style=none)
<a name="MiL6f"></a>
#### 优化2
打包的文件肯定越少越好,第三方库就没必要每次都去打包了,一般项目内第三方库还不少,完全可以去配置CDN,然后这部分第三方库就不用打包了
配置CDN前:vender包合集有7.71Mb,非常吓人哈
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/83039841ff804514b4fdd87f967a1664~tplv-k3u1fbpfcp-watermark.image#id=uT04L&originHeight=118&originWidth=1276&originalType=binary&status=done&style=none)
配置CDN后:vender包合集下降到1.95Mb,还挺给力
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/327e6a59538b4ec69c2ce35f49a48344~tplv-k3u1fbpfcp-watermark.image#id=c11zY&originHeight=116&originWidth=1290&originalType=binary&status=done&style=none)
**打包速度优化效果: 20s -> 13s左右**
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/729f6a4c29b7487cbd7383f33575d87e~tplv-k3u1fbpfcp-watermark.image#id=aMFxs&originHeight=108&originWidth=534&originalType=binary&status=done&style=none)
如何配置CDN(webpack工程),可以参考博主的姊妹篇:[webpack工程项目中配置第三方库的CDN,并做CDN容错](https://juejin.cn/post/6950825799406600199)
<a name="w9t2q"></a>
#### 优化3
插件 hard-source-webpack-plugin : [https://www.npmjs.com/package/hard-source-webpack-plugin](https://www.npmjs.com/package/hard-source-webpack-plugin)
作用:它为模块提供了一个中间缓存步骤。为了看到结果,你需要使用这个插件运行 webpack 两次: 第一次构建将花费正常的时间。第二次建设将是显着的更快。
**第二次打包时间能优化到了3s左右**
<a name="vewxG"></a>
#### 优化4
获取打包后,各个资源大小占比情况:[https://www.npmjs.com/package/webpack-bundle-analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer)
使用插件:
```javascript
// npm install -D webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
优化点举例:
用这个插件可以很轻易的找出一些过大的包,比如loadsh,可以按需引入
// npm i -D lodash.clonedeep
import clonedeep from 'lodash.clonedeep'
import('lodash.clonedeep').then(clonedeep => {
})
moment语言包也可以按需引入(比如你只需要中文,其他语言可以不要加载)
以上是把所有语言包给屏蔽了,所以需要自己手动引入需要的语言包
```javascript const webpack = requrie(‘webpack’)
plugins: [ // 忽略moment语言包 new webpack.IgnorePlugin({ resourceRegExp: /^.\/locale$/, contextRegExp: /moment$/, }), ]
```javascript
// ./src/index.js
import 'moment/locale/zh-cn.js' // 最好放上面,先加载语言包
import moment from 'moment'
- 有些陌生库你不知道他有多大
- 比如,博主之前自己写的内部公共组件库内 的一个公共组件加了brace(功能是做一个在线代码编辑器),结果brace包包含了各种语言,打包后还有8M。。。解决方法:只引入业务需要的部分,比如sql,js等
优化5
使用webpack插件DllPlugin
原理:
某些不会改动的代码(如公共库),或体积很大又不常动的代码。把这些代码只需打包一次,下次就不用在打包 直接引用。这样就可以提高打包速度了
- 比如:把公共库打包成一个单独的库文件,每次只需打包业务代码就行了,这样就减少了公共打包的那部分时间,整体速度得到了提升(此处公共库也可以用CDN替代)
- 除了公共库,一些体积很大,耗时很长,又不常动的代码,也可以用此插件
如何使用DllPlugin(具体操作):https://segmentfault.com/a/1190000022441293
原创整理,有错误可留言,如有用,谢谢点赞~