Webpack4 HappyPack增加编译进程数

Webpack4 HappyPack增加编译进程数1 HappyPack 在用 Webpack 构建项目时有大量文件需要解析和处理 构建过程是文件读写和计算密集型的操作 特别是当文件数量变多后 Webpack 构建慢的问题会显得严重 运行在 Node js 之上的 Webpack 是单线程模型的 也就是说 Webpack 需要处理的任务需要一件件挨着做 不能多个事情一起做 文件读写和计算操作是无法避免的 那能不能让 Webpack 同一时刻处理

1.HappyPack

在用Webpack构建项目时有大量文件需要解析和处理,构建过程是文件读写和计算密集型的操作(特别是当文件数量变多后),Webpack 构建慢的问题会显得严重。

运行在 Node.js 之上的 Webpack 是单线程模型的,也就是说 Webpack 需要处理的任务需要一件件挨着做,不能多个事情一起做。

文件读写和计算操作是无法避免的,那能不能让 Webpack 同一时刻处理多个任务,发挥多核 CPU 电脑的威力,以提升构建速度呢?

HappyPack 就能让 Webpack 做到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。

由于 JavaScript 是单线程模型,要想发挥多核 CPU 的能力,只能通过多进程去实现,而无法通过多线程实现。

2.提升Webpack构建速度

1.新建一个项目

|-- node_modules |-- package-lock.json |-- package.json |-- src | |-- index.html
| |-- common.js | `-- main.js `-- webpack.config.js 

package.json

{ 
    "name": "testjsloader", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { 
    "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack --mode development", "build": "webpack --mode production" }, "author": "liujun", "license": "ISC", "devDependencies": { 
    "@babel/core": "^7.5.5", "@babel/preset-env": "^7.5.5", "babel-loader": "^8.0.0-beta.0", "css-loader": "^3.2.0", "style-loader": "^1.0.0", "webpack": "^4.35.3", "webpack-cli": "^3.3.6", "happypack": "^5.0.1" }, "dependencies": { 
    "jquery": "^3.4.1" } } 

1.分别安装了开发的依赖 和 生成的依赖包( 本文主要是介绍:happypack 开发依赖包提升构建速度 )

2.编写了2个打包的脚本

webpack.config.js

const path = require('path'); module.exports = { 
    entry: ['./src/main.js'], output: { 
    // 1.指定输出的文件的名称为 bundle.js ( 默认为main.js ) filename: 'bundle.js', // 2. 指定输出文件存放的目录(默认是dist目录) path: path.resolve(__dirname, './dist'), // 借助node的path模块来拼接一个绝对路径 }, module: { 
    rules: [ { 
    test: /\.js$/, // 匹配 .css 结尾的文件,注意test的值不是一个字符串,而是一个正则 exclude: /(node_modules|bower_components)/, use: [ { 
    loader: 'babel-loader', options: { 
    // 2.使用bable,新语法转成es5语法 presets: [ '@babel/preset-env' ] } } ], }, { 
    test: /\.css$/, // 注意:loaders 是use 的别名 loaders: [ { 
    loader: 'style-loader', options: { 
    } }, { 
    loader: 'css-loader', options: { 
    url: true, import: true } } ], // 给css-loader传递参数 ?minimize } ] } }; 

common.js

import $ from 'jQuery' // 1.箭头函数 和 const 是es6新的语法。目的是要把es6新的语法转成es5语法 const showHelloWorld =(content) => { 
    $('body').css({ 
    background:'pink' }) } // 通过 CommonJS 规范导出 showHelloWorld 函数 module.exports = showHelloWorld; 

main.js

// 1.通过 CommonJS 规范导入 showHelloWorld 函数 const showHelloWorld = require('./common.js'); // 2.执行 showHelloWorld 函数 showHelloWorld('Webpack的安装和使用'); 

index.html

<html> <head> <meta charset="UTF-8">  
     head> <body> <div id="app"> 
      div>  
      <script src="../dist/bundle.js"> 
       script>  
        body>  
         html> 

2.打开终端,在项目的根目录执行:npm run dev 命令就可以开始打包

2.使用HappyPack提升构建速度

webpack.config.js

const path = require('path'); const HappyPack = require('happypack'); module.exports = { 
    entry: ['./src/main.js'], output: { 
    // 1.指定输出的文件的名称为 bundle.js ( 默认为main.js ) filename: 'bundle.js', // 2. 指定输出文件存放的目录(默认是dist目录) path: path.resolve(__dirname, './dist'), // 借助node的path模块来拼接一个绝对路径 }, module: { 
    rules: [ { 
    test: /\.js$/, // 匹配 .css 结尾的文件,注意test的值不是一个字符串,而是一个正则 exclude: /(node_modules|bower_components)/, // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例 use: ['happypack/loader?id=babel'], }, { 
    test: /\.css$/, // 把对 .css 文件的处理转交给 id 为 css 的 HappyPack 实例 use: ['happypack/loader?id=css'], } ] }, plugins: [ new HappyPack({ 
    // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件 id: 'babel', // 如何处理 .js 文件,用法和 Loader 配置中一样 // 注意:loaders 是 use 的别名 loaders: [ { 
    loader: 'babel-loader', options: { 
    // 2.使用bable,新语法转成es5语法 presets: [ '@babel/preset-env' ] } } ] // ... 其它配置项 }), new HappyPack({ 
    id: 'css', // 如何处理 .css 文件,用法和 Loader 配置中一样 loaders: [ { 
    loader: 'style-loader', options: { 
    } }, { 
    loader: 'css-loader', options: { 
    url: true, import: true } } ], // 给css-loader传递参数 ?minimize }) ] }; 

2.打开终端,在项目的根目录执行:npm run dev 命令就可以开始打包, 就会看到以下由 HappyPack 输出的日志:

PS F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程> npm run dev > testjsloader@1.0.0 dev F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程 > webpack --mode development Happy[babel]: Version: 5.0.1. Threads: 3 Happy[babel]: All set; signaling webpack to proceed. Happy[css]: Version: 5.0.1. Threads: 3 Happy[css]: All set; signaling webpack to proceed. ..... ..... 

说明你的 HappyPack 配置生效了,并且可以得知 HappyPack 分别启动了3个子进程去并行的处理任务。

3.指定HappyPack的子进程数

在new HappyPack ( { } ) 插件的时候,除了可以传入 idloaders 两个参数外,HappyPack 还支持threads , threads 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。

webpack.config.js

const path = require('path'); const HappyPack = require('happypack'); module.exports = { 
    entry: ['./src/main.js'], output: { 
    filename: 'bundle.js', path: path.resolve(__dirname, './dist'), }, module: { 
    rules: [ { 
    test: /\.js$/, exclude: /(node_modules|bower_components)/, use: ['happypack/loader?id=babel'], }, { 
    test: /\.css$/, use: ['happypack/loader?id=css'], } ] }, plugins: [ new HappyPack({ 
    id: 'babel', loaders: [ { 
    loader: 'babel-loader', options: { 
    presets: [ '@babel/preset-env' ] } } ], // ... 其它配置项 threads: 5 // 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。 }), new HappyPack({ 
    id: 'css', loaders: [ { 
    loader: 'style-loader', options: { 
    } }, { 
    loader: 'css-loader', options: { 
    url: true, import: true } } ], // ... 其它配置项 threads: 5 // 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。 }) ] }; 

2.打开终端,在项目的根目录执行:npm run dev 命令就可以开始打包, 就会看到以下由 HappyPack 输出的日志:

PS F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程> npm run dev > testjsloader@1.0.0 dev F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程 > webpack --mode development Happy[babel]: Version: 5.0.1. Threads: 5 Happy[babel]: All set; signaling webpack to proceed. Happy[css]: Version: 5.0.1. Threads: 5 Happy[css]: All set; signaling webpack to proceed. 

说明你的 HappyPack 配置生效了,并且可以得知 HappyPack 分别启动了5个子进程去并行的处理任务。

4.HappyPack共享子进程

在new HappyPack ( { } ) 插件的时候,除了可以传入 id , loadersthreads 参数外,HappyPack 还支持threadPool, threadPool 代表共享进程池,即多个 HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多。

webpack.config.js

const path = require('path'); const HappyPack = require('happypack'); // 构造出共享进程池,进程池中包含5个子进程 const happyThreadPool = HappyPack.ThreadPool({ 
    size: 5 }); module.exports = { 
    entry: ['./src/main.js'], output: { 
    filename: 'bundle.js', path: path.resolve(__dirname, './dist'), }, module: { 
    rules: [ { 
    test: /\.js$/, exclude: /(node_modules|bower_components)/, use: ['happypack/loader?id=babel'], }, { 
    test: /\.css$/, use: ['happypack/loader?id=css'], } ] }, plugins: [ new HappyPack({ 
    id: 'babel', loaders: [ { 
    loader: 'babel-loader', options: { 
    presets: [ '@babel/preset-env' ] } } ], // ... 其它配置项 threads: 5, // 使用共享进程池中的子进程去处理任务 threadPool: happyThreadPool, }), new HappyPack({ 
    id: 'css', loaders: [ { 
    loader: 'style-loader', options: { 
    } }, { 
    loader: 'css-loader', options: { 
    url: true, import: true } } ], // ... 其它配置项 threads: 5, // 使用共享进程池中的子进程去处理任务 threadPool: happyThreadPool, }) ] }; 

打开终端,在项目的根目录执行:npm run dev 命令, 这时你会看到控制台有一串日志输出:

PS F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程> npm run dev > testjsloader@1.0.0 dev F:\blog\webpack-study\webpackCode\11-HappyPack增加编译进程 > webpack --mode development Happy[babel]: Version: 5.0.1. Threads: 5 Happy[babel]: All set; signaling webpack to proceed. Happy[css]: Version: 5.0.1. Threads: 5 Happy[css]: All set; signaling webpack to proceed. 

总结:

在整个 Webpack 构建流程中,最耗时的流程可能就是 Loader 对文件的转换操作了,因为要转换的文件数据巨多,而且这些转换操作都只能一个个挨着处理。

HappyPack 的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少了总的构建时间。

从前面的使用中可以看出所有需要通过 Loader 处理的文件都先交给了 happypack/loader 去处理,收集到了这些文件的处理权后 HappyPack 就好统一分配了。

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

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

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

源码下载

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176589.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午9:33
下一篇 2026年3月26日 下午9:33


相关推荐

  • SGD随机梯度下降_随机梯度法

    SGD随机梯度下降_随机梯度法BGDvsSGDBGDvsSGD名词解释功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入BGDvsSGD…

    2025年10月21日
    3
  • mysql查找最后一条记录_mysql查询记录总数

    mysql查找最后一条记录_mysql查询记录总数首先要确定什么是最后一条。是编辑时间最新的为最后一条,还是某个字段数字最大的未最后一条。比如以时间最大为最后一条,则将符合条件的资料都筛选出来,再按时间排序,再取一笔资料。SQL如下:selecta,bfromtablewherea&gt;’某个时间’orderbyadesclimit1(上面SQL中a为时间)。用max(time)查询方可!!…

    2025年10月2日
    5
  • IntelliJ IDEA 配置svn及使用

    IntelliJ IDEA 配置svn及使用1.安装svn客户端之前用myEcplise只需要插件,现在IDEA需要先下载客户端:TortoiseSVN(小乌龟),下载后安装,然后记住安装路径,我安装的是64位的。TortoiseSVN的下载地址:https://tortoisesvn.net/downloads.html下载完成之后然后开始运行安装svn在勾选之前记得要安装改路径,例:F:\svnClient…

    2022年5月15日
    75
  • OpenClaw 定时任务cron配置指南:飞书渠道避坑详解

    OpenClaw 定时任务cron配置指南:飞书渠道避坑详解

    2026年3月13日
    1
  • 中标麒麟安装deb命令_麒麟源码

    中标麒麟安装deb命令_麒麟源码**中标麒麟NeoKylin-SDK里都有哪些库文件**下边是中标麒麟1-8和14的安装包内容。希望对中标麒麟开发的同学能有些帮助。[root@bogonNeoKylin-SDK]#shinstall.shPleaseselectwhichgroupyouwanttoinstall:1)C-development5)gnome-soft…

    2022年8月10日
    96
  • 时光网打不开的解决办法

    时光网打不开的解决办法2010年11月4日Update:时光网已回归.在C:\Windows\System32\drivers\etc文件夹中打开hosts文件,以文本格式打开。(Windows7和Vista可能需要复

    2022年7月2日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号