You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importtestfrom"node:test";importassertfrom"node:assert";test("synchronous passing test",(t)=>{// This test passes because it does not throw an exception.assert.strictEqual(1,1);});
/** * Runs iterator function in parallel. * @template T - The type of items in the data source * @param {number} maxConcurrency - The maximum concurrency. * @param {Array<T>} source - The data source * @param {(item: T) => Promise<void>} iteratorFn - The iteratorFn * @returns {Promise<void[]>} - A Promise array containing all iteration results. */asyncfunctionrunParallel(maxConcurrency,source,iteratorFn){/**@type {Promise<void>[]} */constret=[];/**@type {Promise<void>[]} */constexecuting=[];for(constitemofsource){constp=Promise.resolve().then(()=>iteratorFn(item));ret.push(p);if(maxConcurrency<=source.length){conste=p.then(()=>{executing.splice(executing.indexOf(e),1);});executing.push(e);if(executing.length>=maxConcurrency){awaitPromise.race(executing);}}}returnPromise.all(ret);}
最近在给公司内部低代码平台进行升级,原本是单一仓库,里面有各种模块,例如:
它们最终给其他产品线使用的时候是通过 Vue Cli 打包成一个 umd 的 js 文件,但是这样会带来一系列问题,所以就准备调整成 monopore 的形式,讲上面的模块拆分成一个个的单体仓库,以及后续版本发布也会基于 npm 的形式来管理。
但是首先摆在眼前的就是对 packages 下目录的包要如何进行构建分发,这里调研了下最终参考 Vue 的构建过程。
这篇文章不介绍 Vue 是如何构建整个流程的,只是介绍在构建中可以收获什么知识点。
node:
前缀打开 scripts/build.js 文件,映入眼帘的就是
node:
前缀名称。你可能很好奇,之前使用 node 包的时候都是直接引入呀,为什么现在还出现了这种语法。
其实这个是 node18 引入的特性,简单来说就是 node18 引入了一些新模块,例如 test,但是 test 这个 npm 上已经有了,这样的话就会有歧义,到底你要使用 node 的包还是 npm 别人发布的呢?
所以就添加了
node:
的前缀其次,因为
node:
是官方的前缀,也可以一定程度避免安全性问题,例如可能会有一个包叫做expres
它跟express
非常接近,可能会存在误导性。还有也会带来性能上的提升,有了
node:
前缀可以避免查找node_modules
目录这一过程,直接加载内置模块。补充阅读
控制并发数量
在 build 过程中,如果一个个顺序调用会导致构建时间太长了,就需要有一个机制来管理并发数量
这个函数会在
buildAll
调用这个函数会通过
await
特性来调整并发数量,简单概括一下流程这里补充一下 if 是如何工作的
整体流程就是这样,可以理解 all 会一次性并发掉所有 maxConcurrency 数量的任务,如果 source 任务数量大于 maxConcurrency 则会在 if 语句中剔除掉
execa
这里并没有直接调用 rollup 的 api 来完成构建,我觉得这点也可以说下
buildAll
这个函数用到了cpus().length
,基于 cpu 的核心数量来构建任务。每次 execa 都会创建一个子进程,可以最大程度利用机器性能,虽然没有通过多进程的形式来构建,但是多进程的创建也是一笔花销。
其次
stdio: "inherit"
的意思是进程将共享当前进程的标准输入、输出和错误流。也就是说,子进程的输出会直接显示在当前进程的控制台上,输入也会直接来自当前进程的控制台。这样我们就会看到 rollup 的打包的信息生成在控制台中。
require
require 是 cjs 的导入模块标准,它不同于 esm 会同步加载模块。但是有的时候也会想使用 require,例如加载一个 json 文件,如果不通过 require 就需要通过
import()
的语法了,import()
是一个异步 api,所以就会带来一些问题。再来看 Vue 是怎么处理的。
通过
createRequire
创建了 require,这样就可以在 esm 模块中导入 cjs 的模块了。例如在这里就直接读取了对应 packages 下的 package.json 文件了
rm
node 默认的 fs.rm 只会删除一层目录,如果目录里面嵌套目录就会导致删除不了。
因此会有一系列包,但是 node 现在支持删除嵌套目录了,使用方法也很简单,通过
recursive
选项。这里也可以聊一下
existsSync
这个 api,它会判断对应的文件或者目录是否存在,是一个同步语法,虽然在 node 中提倡使用异步语法,但是有一些情况使用同步语法更合适。最后
如果内容有错误地方欢迎指出。
The text was updated successfully, but these errors were encountered: