HappyPack 并行编译提高 Webpack 构建速度

发布于 2022-04-22 12:58:12 字数 7294 浏览 1240 评论 0

HappyPack 通过并行转换文件使初始 webpack 构建更快。

维护模式通知

我对这个项目的兴趣正在消退,主要是因为我没有像过去那样使用 JavaScript。此外,Webpack 的本机性能正在提高,(我希望)它很快就会使这个插件变得不必要。

请参阅有关 Webpack 4 和thread-loader的 FAQ 条目。

用法

npm install --save-dev happypack

HappyPack 提供了一个插件和一个加载器来完成它的工作,所以你必须同时使用它们来启用它。

通常,您定义加载器规则来告诉 webpack 如何处理某些文件。使用 HappyPack,您可以进行切换,以便将加载器传递给 HappyPack 的插件,而不是告诉 webpack 使用happypack/loader.

以下是显示这些步骤的示例配置。

// @file: webpack.config.js
const HappyPack = require('happypack');

exports.module = {
  rules: [
    {
      test: /.js$/,
      // 1) replace your original list of loaders with "happypack/loader":
      // loaders: [ 'babel-loader?presets[]=es2015' ],
      use: 'happypack/loader',
      include: [ /* ... */ ],
      exclude: [ /* ... */ ]
    }
  ]
};

exports.plugins = [
  // 2) create the plugin:
  new HappyPack({
    // 3) re-add the loaders you replaced above in #1:
    loaders: [ 'babel-loader?presets[]=es2015' ]
  })
];

就是这样。现在匹配的源.js$将被移交给 HappyPack,HappyPack 将使用您指定的加载器并行转换它们(babel-loader 在本例中。)

配置

这些是您在实例化插件时可以传递给插件的参数。 loaders是唯一必需的参数。

loaders: Array

每个条目都包含将转换文件的加载程序的名称(或绝对路径)和传递给它的可选查询字符串。这看起来类似于您传递给 webpackloader配置的内容。

小心!HappyPack 不适用于所有webpack 加载器,因为某些加载器 API 不受支持,有关当前 Loader API 支持的更多详细信息,请参阅此 wiki 页面。

以下符号是官方支持的,并且都是等效的:

{
  loaders: [
    // a string with embedded query for options
    'babel-loader?presets[]=es2015',

    {
      loader: 'babel-loader'
    },

    // "query" string
    {
      loader: 'babel-loader',
      query:  '?presets[]=es2015'
    },

    // "query" object
    {
      loader: 'babel-loader',
      query: {
        presets: [ 'es2015' ]
      }
    },

    // Webpack 2+ "options" object instead of "query"
    {
      loader: 'babel-loader',
      options: {
        presets: [ 'es2015' ]
      }
    }
  ]
}

id: String

这个快乐插件的唯一 ID。加载器使用它来知道它应该与哪个插件通信。

通常,除非您定义了多个 HappyPack 插件,否则您不需要指定这一点,在这种情况下,您需要不同的 ID 来区分它们。有关详细信息,请参阅本节

默认为:"1"

threads: Number

此数字表示将生成多少个 Node VM HappyPack 用于编译源文件。经过大量的修补,我发现 4 可以产生最好的结果。这个值的回报肯定会递减,而超过 8 的值实际上会减慢我的速度。

请记住,这仅在执行初始构建时才相关, 因为 HappyPack 将在之后切换到同步模式(即在watch 模式中。)

默认为:3

threadPool: HappyThreadPool

用于检索工作线程的预定义线程池。通常,这是由每个HappyPlugin实例在内部管理的,但您可以覆盖此行为以获得更好的结果。

线程池部分解释了如何以及何时使用它。

默认为:null

verbose: Boolean

启用它以将状态消息从 HappyPack 记录到 STDOUT,如启动横幅等。

默认为:true

verboseWhenProfiling: Boolean

如果您希望 HappyPack 即使在webpack --profile运行时仍能产生其输出,请启用此选项。由于引入了这个变量,HappyPack 在构建配置文件时将保持沉默,以免破坏 webpack 的任何 JSON 输出(即在使用时--json也是如此。)

默认为:false

debug: Boolean

启用此选项可将 HappyPack 的诊断消息记录到 STDOUT。对故障排除很有用。

默认为:false

这个怎么运作

HappyPack 位于 webpack 和您的主要源文件(如 JS 源文件)之间,其中大部分加载器转换发生。每次 webpack 解析一个模块时,HappyPack 都会获取它及其所有依赖项并将这些文件分发到多个工作“线程”。

这些线程实际上是调用转换器的简单节点进程。当检索到编译后的版本时,HappyPack 将其提供给它的加载器并最终提供给您的块。

使用多个实例

可以为不同类型的源/转换定义多个 HappyPack 插件。只需为每个插件传递一个唯一的 id 并确保将其传递给它们的加载器:

// @file webpack.config.js
exports.plugins = [
  new HappyPack({
    id: 'jsx',
    threads: 4,
    loaders: [ 'babel-loader' ]
  }),

  new HappyPack({
    id: 'styles',
    threads: 2,
    loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
  })
];

exports.module.rules = [
  {
    test: /\.js$/,
    use: 'happypack/loader?id=jsx'
  },

  {
    test: /\.less$/,
    use: 'happypack/loader?id=styles'
  },
]

现在.js文件将由第一个 babel-loader用于转换它们的 Happy 插件处理,而.less文件将由第二个使用样式加载器的插件处理。

共享线程池

通常,您在内部创建的每个 HappyPack 插件都会创建自己的线程,用于运行加载程序。但是,如果您使用多个 HappyPack 插件,最好自己创建一个线程池,然后将插件配置为共享该池,从而最大限度地减少其中线程的空闲时间。

这是一个使用 5 个线程的自定义池的示例,它将在 JS 和 SCSS/LESS/任何来源的加载器之间共享:

// @file: webpack.config.js
var HappyPack = require('happypack');
var happyThreadPool = HappyPack.ThreadPool({ size: 5 });

module.exports = {
  // ...
  plugins: [
    new HappyPack({
      id: 'js',
      threadPool: happyThreadPool,
      loaders: [ 'babel-loader' ]
    }),

    new HappyPack({
      id: 'styles',
      threadPool: happyThreadPool,
      loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
    })
  ]
};

基准

对于我测试过的主存储库,它有大约 3067 个模块,构建时间从 39 秒下降到了大约 10 秒。

以下是执行构建的各种状态的概要:

Elapsed (ms)Happy?Using DLLs?
39851NONO
37393NOYES
14605YESNO
13925YESNO
11877YESNO
9228YESYES

上面的构建是在一台 12 核机器上的 Linux 下运行的。

常问问题

它适用于 Webpack 2 和 3 吗?

是的。您应该使用版本 >= 4.0.1(HappyPack)。

Webpack 4 有必要吗?

简短的回答:也许不是。

长答案:现在有一个加载器形式的竞争插件,用于在多个线程中处理文件,这正是 HappyPack 所做的。它是一个加载器而不是一个插件(或两者,如果是 HP),这一事实使得配置变得更加简单。看看线程加载器,如果它对你有用——那很好,否则你可以试试 HappyPack 看看哪个更适合你。

YMMV。

它适用于 TypeScript 吗?

简短的回答是:是的,它终于做到了!更长的答案是您需要在“仅转译”模式下使用 ts-loader ,然后使用特殊插件 fork-ts-checker-notifier-webpack-plugin执行静态类型检查。

更多信息可以在 ts-loader “happypack mode” 部分中找到,您可以参考显示此操作的 示例。

非常感谢 @johnnyreilly、@aindlq、@piotr-oles、@abergs 和许多其他人完成这项工作。

它适用于装载机 XYZ 吗?

我们在这个 wiki 页面中跟踪加载器支持。一些加载器可能需要额外的配置才能使其工作。

如果您尝试使用的加载器未在此处列出,您可以参考wiki 页面以查看支持哪些加载器 API。如果您的 loader 使用任何不受支持的 API,它很可能无法与 HappyPack 一起使用。

作为一般规则,任何在选项中接受“函数”的加载器都不会工作,除非它也接受从文件中读取这些选项,就像 babel-loader.babelrc和 postcss-loader 一样。

它在 Windows 下工作吗?

是的,从 4.0.0 版开始应该。如果您在 Windows 上使用该插件时遇到问题,请随时提问。

项目地址:https://github.com/amireh/happypack

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84935 人气
更多

推荐作者

    原文
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。