webpack配置优化

前言

在项目测试阶段、不断的需求迭代、现场遇到问题后,每改动一次代码,前端需要重新打包部署到测试环境或者生产环境,打包过程以及首屏加载非常慢,影响到了开发体验以及用户体验。

目标

  1. 优化构建速度、优化使用体验、优化输出质量
  2. 部分替换前端包,避免整体替换引发的不可预知问题

优化构建速度、优化使用体验、优化输出质量

导入文件时带上文件后缀,缩小文件的搜索范围

webapck在启动后会从配置的entry出发,解析出文件中的导入语句,再递归解析;过程:根据导入语句去寻找对应的导入的文件-->根据找到的要导入的文件的后缀,使用配置中的Loader去处理文件

resolve.extensions后缀列表尽可能少,频率高的文件后缀靠前

动态链接库(第三方npm包)只需要被编译一次,可以提前构建

  1. 新建webpack.dll.conf.js文件,以oms项目为例
const path = require('path')
const webpack = require('webpack')

module.exports = {
  // 你想要打包的模块的数组
  entry: {
    vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'element-ui', 'crypto-js', 'moment', 'echarts', 'md5', 'vuex-persistedstate']
  },
  output: {
    path: path.join(__dirname, '../static/dll'), // 打包后文件输出的位置
    filename: '[name].dll.js',
    library: '[name]_library'
    // vendor.dll.js中暴露出的全局变量名。
    // 主要是给DllPlugin中的name使用,
    // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '../static/dll', '[name]-manifest.json'),
      name: '[name]_[chunkhash]',
      context: __dirname
    }),
    // 压缩打包的文件,与该文章主线无关
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  1. 修改webpack.prod.conf.js
// plugin扩展增加以下代码
new webpack.DllReferencePlugin({
  manifest: require('../static/dll/vendor-manifest.json')
})
1
2
3
4
  1. 修改package.json,增加npm run build:dll命令,提前构建
"scripts": {
  "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
  "start": "npm run dev",
  "e2e": "node test/e2e/runner.js",
  "test": "npm run e2e",
  "lint": "eslint --ext .js,.vue src test/e2e/specs",
  "build": "node build/build.js",
  "build:dll": "webpack --config build/webpack.dll.conf.js"
}
1
2
3
4
5
6
7
8
9

Happypack多线程处理文件

在整个webpack构建流程中,最耗时的可能就是Loader对文件的转换,webpack是单线程模型,webpack需要一个一个去处理任务,不能同时处理多个任务,HappyPack的核心原理就是将这部分任务分解到多个进程中去并行处理,从而减少总的构建时间

// 修改webpack.base.conf.js,扩展plugin
new HappyPack({
  id: 'happyBabel',
  loaders: [{
    loader: 'babel-loader?cacheDirectory=true'
  }],
  threadPool: happyThreadPool
}),
new HappyPack({
  id: 'happyScss',
  loaders: ['style-loader', 'css-loader', 'sass-loader'],
  threadPool: happyThreadPool
})
1
2
3
4
5
6
7
8
9
10
11
12
13

多线程压缩

当webpack有多个javascript文件需要输出和压缩时,原本会使用UglifyJS去一个 一个压缩再输出(uglifyJs在构建用于线上的代码时会卡在一个时间点上迟迟没有反应),但ParalleUglifyPlugin会开启多个线程,将对多个文件的压缩工作分配给多个子进程去完成,每个子进程其实还是通过UglifyJS去压缩代码,但是变成了并行执行

// 以oms为例,修改webpack.prod.conf.js,扩展plugin
new ParallelUglifyPlugin({
  uglifyES: {
    output: {
      beautify: false,
      comments: false
    },
    compress: {
      warnings: false
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12

部分替换前端包

路由懒加载