前端开发体验提升-webpack打包速度优化

本篇主题是:webpack打包速度优化

准备分2步:

  1. 如何发现打包速度慢?(精确到哪个plugin慢,哪个loader慢)
  2. 如何解决慢的问题?

进入正题

如何发现打包速度慢?(精确到哪个plugin慢,哪个loader慢)

安装插件:speed-measure-webpack-plugin: https://www.npmjs.com/package/speed-measure-webpack-plugin

  • 注:webpack5以上,可能会有问题

配置speed-measure-webpack-plugin的方法:

  1. // 修改你的 webpack 配置
  2. // 把以下这种对象
  3. const webpackConfig = {
  4. entry: '',
  5. output: '',
  6. plugins: [new MyPlugin(), new MyOtherPlugin()],
  7. };
  8. // 写成以下这种
  9. const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
  10. const smp = new SpeedMeasurePlugin();
  11. const webpackConfig = smp.wrap({
  12. entry: '',
  13. output: '',
  14. plugins: [new MyPlugin(), new MyOtherPlugin()],
  15. });

npm run build 后,效果如下

前端开发体验提升-webpack打包速度优化(30s -> 13s,第2次打包到3s) - 图1

可以看到对应plugin和loader的耗时

知道了哪些地方慢之后,开始想办法解决慢的地方

如何解决慢的问题?

首先把官网推荐的优化操作,先给弄下来

(有些优化操作 新版本webpack已经内置了):https://webpack.docschina.org/guides/build-performance/#babel

整理出几个要操作的小点:

  1. 使用最新的版本(新版会有性能优化)
    • 比如 用最新版的:webpack,node,各种loader和plugin
  1. 通过使用 include 字段,仅将 loader 应用在实际需要将其转换的模块: ```javascript const path = require(‘path’);

module.exports = { //… module: { rules: [ { test: /.js$/, include: path.resolve(__dirname, ‘src’), // 避免去扫描 node_modules loader: ‘babel-loader’, }, ], }, };

  1. 3. DevtoolsourceMap
  2. - 用于生产(正式)环境中:(none)(或省略 devtool 选项) - 不生成 source map (减小体积)
  3. - 正式环境也可以无害的使用sourceMap:博主的姊妹篇https://juejin.cn/post/6956047151843508232
  4. - 用于开发(dev)环境中:推荐 eval-source-map
  5. <br />基本的通用方案弄完后,是否就结束了? - 还没结束,还有优化空间,往下看
  6. <a name="Y7Ti8"></a>
  7. ### 分析问题:哪些能优化?哪些动不了?
  8. 排除法,先看看哪些动不了?(此分析案例是vue工程,react工程也可以类似这么分析)
  9. - 一般稳定的第三方loaderwebpack官方插件,本身就已经做了优化,想动源码改造的话,成本过高,收益不明显。几乎可以忽略,比如:vue-loadercss-loadersass-loaderless-loader
  10. 除了“基本的开发标配”后,需开发者自己在去检查,项目内是否用了什么会耗时的插件。
  11. 举例:以博主接手的老公司项目来说,用上面讲的speed-measure-webpack-plugin插件,分析出能够操作的耗时项(一般是开发者自己额外添加的loaderplugin
  12. <a name="B5j1m"></a>
  13. #### 优化1
  14. 检测到<br />`_image-webpack-loader@4.6.0@image-webpack-loader took 12.081 secs`
  15. - image-webpack-loader:耗时12s。(其余的均为基本插件和loader,优化空间很小)
  16. - 了解到image-webpack-loader的作用是压缩图片,并且每次打包都会重新压缩图片,太费时间。所以可以考虑,所有图片一次性压缩好(可以用https://tinypng.com/ ),然后在这个loader去掉
  17. **打包速度优化效果: 30s -> 20s左右**
  18. ![](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)
  19. <a name="MiL6f"></a>
  20. #### 优化2
  21. 打包的文件肯定越少越好,第三方库就没必要每次都去打包了,一般项目内第三方库还不少,完全可以去配置CDN,然后这部分第三方库就不用打包了
  22. 配置CDN前:vender包合集有7.71Mb,非常吓人哈
  23. ![](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)
  24. 配置CDN后:vender包合集下降到1.95Mb,还挺给力
  25. ![](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)
  26. **打包速度优化效果: 20s -> 13s左右**
  27. ![](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)
  28. 如何配置CDNwebpack工程),可以参考博主的姊妹篇:[webpack工程项目中配置第三方库的CDN,并做CDN容错](https://juejin.cn/post/6950825799406600199)
  29. <a name="w9t2q"></a>
  30. #### 优化3
  31. 插件 hard-source-webpack-plugin [https://www.npmjs.com/package/hard-source-webpack-plugin](https://www.npmjs.com/package/hard-source-webpack-plugin)
  32. 作用:它为模块提供了一个中间缓存步骤。为了看到结果,你需要使用这个插件运行 webpack 两次: 第一次构建将花费正常的时间。第二次建设将是显着的更快。
  33. **第二次打包时间能优化到了3s左右**
  34. <a name="vewxG"></a>
  35. #### 优化4
  36. 获取打包后,各个资源大小占比情况:[https://www.npmjs.com/package/webpack-bundle-analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer)
  37. 使用插件:
  38. ```javascript
  39. // npm install -D webpack-bundle-analyzer
  40. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  41. module.exports = {
  42. plugins: [
  43. new BundleAnalyzerPlugin()
  44. ]
  45. }

前端开发体验提升-webpack打包速度优化(30s -> 13s,第2次打包到3s) - 图2

优化点举例:

  1. 用这个插件可以很轻易的找出一些过大的包,比如loadsh,可以按需引入

    1. // npm i -D lodash.clonedeep
    2. import clonedeep from 'lodash.clonedeep'
    3. import('lodash.clonedeep').then(clonedeep => {
    4. })
  2. moment语言包也可以按需引入(比如你只需要中文,其他语言可以不要加载)
    以上是把所有语言包给屏蔽了,所以需要自己手动引入需要的语言包
    ```javascript const webpack = requrie(‘webpack’)

plugins: [ // 忽略moment语言包 new webpack.IgnorePlugin({ resourceRegExp: /^.\/locale$/, contextRegExp: /moment$/, }), ]

  1. ```javascript
  2. // ./src/index.js
  3. import 'moment/locale/zh-cn.js' // 最好放上面,先加载语言包
  4. import moment from 'moment'
  1. 有些陌生库你不知道他有多大
  • 比如,博主之前自己写的内部公共组件库内 的一个公共组件加了brace(功能是做一个在线代码编辑器),结果brace包包含了各种语言,打包后还有8M。。。解决方法:只引入业务需要的部分,比如sql,js等

优化5

使用webpack插件DllPlugin

原理:

  • 某些不会改动的代码(如公共库),或体积很大又不常动的代码。把这些代码只需打包一次,下次就不用在打包 直接引用。这样就可以提高打包速度了

    • 比如:把公共库打包成一个单独的库文件,每次只需打包业务代码就行了,这样就减少了公共打包的那部分时间,整体速度得到了提升(此处公共库也可以用CDN替代)
    • 除了公共库,一些体积很大,耗时很长,又不常动的代码,也可以用此插件


    如何使用DllPlugin(具体操作):https://segmentfault.com/a/1190000022441293


原创整理,有错误可留言,如有用,谢谢点赞~