Webpack从手把手配置到原理浅析(四):构建速度优化

834 阅读2分钟

在开发过程中,源文件经常要被修改,免不了要重新构建打包,才能看到修改后的效果。这时候构建速度就显得尤为重要,构建速度的优化能极大地提高开发效率和体验。 本文介绍一些常见的Webpack优化构建速度的方法。

优化babel-loader

babel-loader的作用是将ES6及以上的语法转译为浏览器能识别的ES5语法,速度很慢。所以优化的点在于:

  1. 明确转译范围,确保转译尽可能少的文件

    明确includeexclude,即告诉Webpack使用babel-loader的文件范围

  2. 使用缓存

    开启babel-loadercacheDirectory选项,当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程。如果设置了一个空值 (loader: 'babel-loader?cacheDirectory') 或者 true (loader: 'babel-loader?cacheDirectory=true'),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。

module: {
  rules: [
    {
      test: /\.js$/,
      loader: ['babel-loader?cacheDirectory'],
      include: srcPath,
      // exclude: /node_modules/
      }
    }
  ]
}

Happypack多进程打包

在使用 Webpack 对项目进行构建时,会对大量文件进行解析和处理。当文件数量变多之后,Webpack 构件速度就会变慢。由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以 Webpack 需要处理的任务要一个一个进行操作。 而 happypack 的作用就是将文件解析任务分解成多个子进程并发执行。子进程处理完任务后再将结果发送给主进程。所以可以大大提升 Webpack 的项目构件速度。 happypack 只是作用在 loader 上,使用多个进程同时对文件进行编译。

1.引入happypack插件

const HappyPack = require('happypack')

module.exports = {
    // ...
    plugins: [
        // happypack 开启多进程打包
        new HappyPack({
            // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件
            id: 'babel',
            // 如何处理 .js 文件,用法和 Loader 配置中一样
            loaders: ['babel-loader?cacheDirectory']
        }),
    ],
}

2.将普通的loader替换为happypack/loader

module.exports = {
    // ...
    module: {
        rules: [
            {
                test: /\.js$/,
                // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例
                use: ['happypack/loader?id=babel'],
                include: srcPath,
                // exclude: /node_modules/
            },
        ]
    },
    // ...
};

ParalleUglifyPlugin多进程压缩JS

happypack多进程打包类似,Webpack压缩也可以开启多进程,webpack-parallel-uglify-plugin就是为了开启并行压缩JS代码而生。

const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')

module.exports = {
    // ...
    plugins: [
     // 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
     new ParallelUglifyPlugin({
         // 传递给 UglifyJS 的参数
         // (还是使用 UglifyJS 压缩,只不过帮助开启了多进程)
         uglifyJS: {
             output: {
                 beautify: false, // 最紧凑的输出
                 comments: false, // 删除所有的注释
             },
             compress: {
                 // 删除所有的 `console` 语句,可以兼容ie浏览器
                 drop_console: true,
                 // 内嵌定义了但是只用到一次的变量
                 collapse_vars: true,
                 // 提取出出现多次但是没有定义成变量去引用的静态值
                 reduce_vars: true,
             }
         }
     })
    ],
}

关于开启多进程

在上面的介绍中,happypackParalleUglifyPlugin都会开启多进程。 多进程打包可以将打包任务分解成多个子任务并发打包,但是不一定都能对项目的构建速度进行优化,要分情况讨论。

  • 项目较大,本身打包速度较慢,那么开启多进程打包确实是可以提升构建速度
  • 项目较小,本身打包速度就很快,开启多进程打包反而会降低构建速度,因为开启多线程需要开销大

结论:不能盲目使用多进程打包,应该要结合自己项目的特点,按需使用。