webpack/7、构建优化

55 阅读3分钟

背景

当项目使用webpak进行打包后,随着项目的迭代,项目体积会越来越大,打包构建的速度会越来越慢。需要使用一些wepack构建优化的方法进行优化。

分析打包速度

使用插件查看webpack 构建期间各个阶段花费的时间

speed-measure-webpack-plugin

测试当前项目构建的时间3次:

image.png

image.png

image.png

分析影响打包速度的因素

1、搜索时间

指的是查找所有依赖花费的时间。

优化方法

1、loader中`test` 、 `include` 、 `exclude`的配置。
a、exclude的优先级比include2、resolve.extensions 
a、频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程。

在项目中的配置

resolve: {
...
    extensions: ['.js', '.vue', '.json'],
    ===> 更改后,实际vue文件引用比js多。
    extensions: ['.vue', '.js', '.json'],
...    
},
  
module:{
  rules:[
    {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig,
        ====> 新增了include
        include:[
          resolve('src'),
        ],
     },
  ]
}

2、解析时间

指的是将不同文件转成js所花费的时间,因为node.js是单线程操作的,所以可采用工具将其多线程化。

thread-loader

注意:

image.png

如果loader有限制,需要把它放到thread-loader的前面,例如:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.s?css$/,
        exclude: /node_modules/,
        // 创建一个 css worker 池
        use: [
          'style-loader',
          'thread-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localIdentName: '[name]__[local]--[hash:base64:5]',
              importLoaders: 1
            }
          },
          'postcss-loader'
        ]
      }
      // ...
    ]
    // ...
  }
  // ...
}  

可能会不清楚什么loader会有这些限制,一旦报错,可以尝试将loader移动到thread-loade前面

优化后的时间,测试3次:

image.png image.png image.png

优化前的时间平均:74s

优化后的时间平均:63s

平均加快首次构建:11s,优化14.8%

3、压缩时间

4、二次打包时间cache-loader

未使用cache-loader

修改后台固定页面的位置三次,所花时间如下: image.png image.png image.png

使用cache-loader

给js+vue+css配置了cache-loader,修改后台固定页面的位置三次,所花时间如下:

image.png image.png image.png

发现时间花费更长了,调查原因是保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的 loader 使用此 loader。

故优化成只对js+vue配置cache-loader image.png image.png image.png

总结

优化前的时间平均:2.591s

优化后的时间平均:2.328s

平均加快二次构建:0.263s,优化10.15%

5、使用externals

通过配置externals,不打包第三方库,只通过cdn引入,一来减少打包时间,二来减少app.js的体积。

配置

# webpack.config.js
...
  plugins:[
  new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true,
      templateParameters: {
        JS_URL: ['VueCdnUrl','ELEMENTCdnUrl'],
        CSS_URL: ['ELEMENTCssUrl'],
      },
    }),
  ],
  externals:{
    "vue": 'Vue',
    "element-ui": 'ELEMENT',
    "echarts":"echarts",
    "xlsx":"XLSX",
    "ali-oss":"OSS",
  },
...

# html
...
  <body>
    <div id="app"></div>
    <% for(let url of JS_URL) {%>
     <script src=<%= url %>></script>
    <% } %>
    <% for(let url of CSS_URL) {%>
     <link rel="stylesheet" href=<%= url %>/>
    <% } %>
    <!-- built files will be auto injected -->
  </body>
...

注意:key为安装的包名,value为第三方资源的全局名称,value的值可通过查看第三方包源代码确认。可以看console验证,如果报错,说明对应的value值写错了。

未配置前的情况

开发模式的情况: image.png

image.png image.png image.png

配置后的情况

开发模式的情况: image.png

image.png image.png image.png

总结

优化前的时间平均:63.33s,app.js大小18.97m

优化后的时间平均:47.81s,app.js大小12.37m

平均加快构建速度:15.52s,优化构建速度24.50%。优化app.js体积34.79%

遇到的问题

在服务器上安装依赖的时候npm install 的时候遇到 gyp info

原因:大概率是你本地的node版本与服务器的node版本不一致导致node-sass版本出问题。

解决:使用nvm将本地的node版本与服务器上的node版本保持一致,然后更新node-sass的版本。我的服务器node版本为10.17.0。推荐安装node-sass@4.9.3

// 先在本地执行如下指令
nvm use v10.17.0 
npm unintstall node-sall
npm install node-sall@4.9.3

node-sass与node对应的版本信息:

image.png

参考资料

玩转 webpack,使你的打包速度提升 90%

node-sass的坑