使用HappyPack

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-02-26

HappyPack

随着项目越来越大,文件数量越来越多的时候,webpack的构建就会越来越慢。

因为运行在node上的webpack依然是单线程模式,需要一个一个的处理任务。

HappyPack就是用来解决这个问题的一个插件,将任务分解成多个子进程,子进程处理完后再将结果交给主线程(与web worker模式一样)。

将所有需要通过Loader处理的文件先交给happypack/loader去处理,然后有HappyPack统一分配,每通过 new HappyPack()实例化一个HappyPack,其实就是告诉HappyPack核心调度器如何通过一系列的Loader去转换一类文件,并且可以指定如何为这类转换操作分配子进程。

核心调度器运行在主进程中,也就是运行webpack的进程中,核心调度器将一个个任务分配给当前空闲的子进程,子进程处理完毕后将结果发送给核心调度器,数据交换是通过进程间的通信API来实现的,核心调度器收到子进程处理完毕的结果后,会通知webpack该文件已处理完毕。

使用

// webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HappyPack = require('happypack');

module.exports = {
  // JS 执行入口文件
  entry: {
    main: './main.js',
  },
  output: {
    // 把所有依赖的模块合并输出到一个 bundle.js 文件
    filename: '[name].js',
    // 输出文件都放到 dist 目录下
    path: path.resolve(__dirname, './dist'),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例
        use: ['happypack/loader?id=babel'],
        // 排除 node_modules 目录下的文件
        // node_modules 目录下的文件都是采用的 ES5 语法,没必要再通过 Babel 去转换
        exclude: path.resolve(__dirname, 'node_modules'),
      },
      {
        // 把对 .css 文件的处理转交给 id 为 css 的 HappyPack 实例
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: ['happypack/loader?id=css'],
        }),
      },
    ]
  },
  plugins: [
    new HappyPack({
      // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件
      id: 'babel',
      // 如何处理 .js 文件,用法和 Loader 配置中一样
      loaders: ['babel-loader?cacheDirectory'],
      // loaders: [
      //   {
      //     loader: 'babel-loader',
      //     options: {
      //       presets: [ 'es2015' ]
      //     }
      //   }
      // ]
    }),
    new HappyPack({
      id: 'css',
      // 如何处理 .css 文件,用法和 Loader 配置中一样
      loaders: ['css-loader'],
    }),
    new ExtractTextPlugin({
      filename: `[name].css`,
    }),
  ],
  devtool: 'source-map' // 输出 source-map 方便直接调试 ES6 源码
};

实例化HappyPack插件时,除了传入idloaders两个参数,还支持如下参数:

threads :代表开启几个子进程去处理这一类型的文件,默认是3个,必须是整数。

verbose :是否允许HappyPack 输出日志,默认是true 。

threadPool :代表共享进程池,即多个HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多

const HappyPack = require('happypack');
// 构建出共享进程池,在进程池中包含5个子进程
const happyThreadPool = HappyPack.ThreadPool({ size : 5 }) ;

new HappyPack({
  id: 'css' ,
  //如何处理.css 文件,用法和Loader 配置中的一样
  loaders: ['css-loader'],
  //使用共享进程池中的子进程去处理任务
  threadPool : happyThreadPool,
}),

用来压缩js文件的ParallelUglifyPlugin插件 也是使用多进程的方式去压缩文件