1 起因
考拉有很多node工程,其中客户端代码client/
和基于egg的服务端server/
混合在一起。由于历史遗留问题,大部分client
下都会有多套构建脚本。比如我负责的工程就包含: 1. client/pc
(webpack2) 2. client/wap
(webpack2) 3. client/wap-vue
(webpack4) 4. ssrClient
(vue-cli)
竟然有四套构建 (キ`゚Д゚´) 再加上对应的npm install
,以及服务端的server/
也需要install
,最终导致构建时间会很长
为了解决这个问题,提升构建效率,我做了@kaola/buildflow
,通过多线程并行构建,按需构建(缓存npm install
和npm run build
的构建结果),大幅提升了构建速度
本文主要介绍了buildflow
的解决方案、实现思路,以及一些有趣的技术细节
2 原理和实现
↓流程示意图↓
![b8770a81ab78f9f3227735c23b14482a.png](https://i-blog.csdnimg.cn/blog_migrate/362ed9b61782c3f27e8a8adf398b5c70.jpeg)
2.1 多线程执行任务
将构建的各种命令合理分配到不同线程中,将总体打包效率最大化
2.1.1 设计易于维护和理解的api
创建一个可执行任务
flow.exec('install wap packages', {
cmd: 'npm i --prefix=./client/wap',
cwd: './'
})
如何串行执行
flow.exec('install wap packages', {
cmd: 'npm i --prefix=./client/wap' })
.exec('build wap packages', {
cmd: 'npm run build --prefix=./client/wap' })
如何多线程并行执行
flow.fork([
flow.exec(...), // 任务1
flow.exec(...), // 任务2
])
并行任务之间可以进行嵌套
flow.fork([
flow.fork([
flow.exec(...), // 任务1
flow.exec(...), // 任务2
])
.exec(...), // 任务3,
flow.exec(...), // 任务4
.exec(...), // 任务5
])
如上伪代码执行顺序,就是1/2/4同时开始执行,当1/2执行结束后3再开始执行,当4执行结束后5开始执行
2.1.2 最大线程数
在运行时,如果不限制线程数,可能会并发执行大量任务,导致机器卡顿,反而会拖累整体构建速度。一般在构建机上执行还好(几十个cpu内核起步),但在本地执行时容易出这种问题
因此,使用线程池来控制最大线程数,数量由cpu虚拟内核数来决定更加合理
// CPU逻辑内核,决定最大并发任务数量
const cpus = require('os').cpus();
const cpuNumber = cpus.length;
一个例子,部分代码如下
完整版见:
https://codesandbox.io/s/middleware-onion-oqzfb?fontsize=14&hidenavigation=1&theme=darkcodesandbox.io![daa7bf87587aec3fc749f3ca84ad24e3.png](https://i-blog.csdnimg.cn/blog_migrate/d572e57994cd330639fff07c963db652.jpeg)