美文网首页
2022-04-17

2022-04-17

作者: 姜浩_19强化班 | 来源:发表于2022-04-17 17:00 被阅读0次

    happyPack与thread-load

    happyPack实现多线程编译

    webpack在node中是单线程的,但是在使用webpack编译项目时,loader、plugin需要处理的文件数量很大,webpack单线程处理导致效率低、速度慢,可以使用happyPack来实现多线程工作。

    happyPack将不同的loader、plugin工作分配到不同的子线程,在子线程结束完后再推入到主线程中,多线程同时编译,减少编译时间。

    基本使用

    const path = require('path');

    const HappyPack = require('happypack');

    module.exports = {

      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'],

          // ... 其它配置项

        }),

        new HappyPack({

          id: 'css',

          // 如何处理 .css 文件,用法和 Loader 配置中一样

          loaders: ['css-loader'],

        }),

        new ExtractTextPlugin({

          filename: `[name].css`,

        }),

      ],

    };

    loader配置中,全部交给happyPck/loader处理,其后的 id=babel告诉happyPck/loader选择哪个happyPack实例处理文件

    plugin中,options中设置的id和loader中使用的id对应。

    实例化happyPack时的其他options

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

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

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

    const HappyPack = require('happypack')

    const os = require('os')

    //os nodejs os模块提供了一些基本的系统操作函数

    const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })

    module.exports = {

        ...

            plugins: [

                new HappyPack({

                    id: 'js',

                    threadPool: happyThreadPool,

                    loaders: ['babel-loader?cacheDirectory=true']

                }),

            ]

    }

    基本原理

    在整个 Webpack 构建流程中,最耗时的流程可能就是Loader对文件的转换操作了,因为要转换的文件数据巨多,而且这些转换操作都只能一个个挨着处理。 HappyPack的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少了总的构建时间。

    所有需要通过Loader处理的文件都先交给了happypack/loader去处理,收集到了这些文件的处理权后HappyPack就好统一分配了。

    每通过new HappyPack()实例化一个HappyPack其实就是告诉HappyPack核心调度器如何通过一系列Loader去转换一类文件,并且可以指定如何给这类转换操作分配子进程。

    核心调度器的逻辑代码在主进程中,也就是运行着Webpack的进程中,核心调度器会把一个个任务分配给当前空闲的子进程,子进程处理完毕后把结果发送给核心调度器,它们之间的数据交换是通过进程间通信API实现的。

    核心调度器收到来自子进程处理完毕的结果后会通知Webpack该文件处理完毕

    thread-load替代happyPack

    happyPack的作者不维护了,现在使用thread-load

    使用thread-load可以实现将不同编译工作放入不同的工作池中运行。

    将thread-load放在其他loader的前面即可,那么在它其后的loader就会单独运行在一个工作池中。

    相关文章

      网友评论

          本文标题:2022-04-17

          本文链接:https://www.haomeiwen.com/subject/luelertx.html