Webpack4 HappyPack增加编译进程数

2024-08-23 22:08

本文主要是介绍Webpack4 HappyPack增加编译进程数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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>
<!--导入 Webpack 输出的 JavaScript 文件-->
<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 developmentHappy[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 developmentHappy[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 developmentHappy[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 该文件处理完毕。

源码下载

这篇关于Webpack4 HappyPack增加编译进程数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100626

相关文章

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

java 进程 返回值

实现 Callable 接口 与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。 public class MyCallable implements Callable<Integer> {public Integer call() {return 123;}} public static void main(String[] args

C#关闭指定时间段的Excel进程的方法

private DateTime beforeTime;            //Excel启动之前时间          private DateTime afterTime;               //Excel启动之后时间          //举例          beforeTime = DateTime.Now;          Excel.Applicat

linux中使用rust语言在不同进程之间通信

第一种:使用mmap映射相同文件 fn main() {let pid = std::process::id();println!(

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

Golang进程权限调度包runtime

关于 runtime 包几个方法: Gosched:让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,因此当前线程未来会继续执行GOMAXPROCS:设置最大的可同时使用的 CPU 核数Goexit:退出当前 goroutine(但是defer语句会照常执行)NumGoroutine:返回正在执行和排队的任务总数GOOS:目标操作系统NumCPU:返回当前系统的 CPU 核数量 p

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.

如何保证android程序进程不到万不得已的情况下,不会被结束

最近,做一个调用系统自带相机的那么一个功能,遇到的坑,在此记录一下。 设备:红米note4 问题起因 因为自定义的相机,很难满足客户的所有需要,比如:自拍杆的支持,优化方面等等。这些方面自定义的相机都不比系统自带的好,因为有些系统都是商家定制的,难免会出现一个奇葩的问题。比如:你在这款手机上运行,无任何问题,然而你换一款手机后,问题就出现了。 比如:小米的红米系列,你启用系统自带拍照功能后