我们如何将 Node.js Monorepo 构建时间缩短 70%
在Novu,我们使用单一仓库 (monorepo) 来管理我们的 24 个库和应用。关于应该使用单一仓库还是多仓库,存在很多争论。对我们来说,可见性、代码共享、标准化、更易于重构以及其他一些因素是我们为开源通知基础设施项目选择此方法的关键因素。
TLDR;
我们从yarn 工作区和lerna迁移到PNPM和nx.dev
越大越慢
尽管 Monorepos 有诸多优点,但也存在一些缺点。我们在扩展包数量和每个包中的代码量时,注意到了一个特别的缺点:启动项目以及构建任何包所需的时间。因此,针对一项服务的典型 GitHub 操作需要 11 到 30 分钟。这还不包括每次创建 PR 或将代码推送到远程仓库的时间。
除此之外,在本地安装包yarn install
可能需要大约 5 分钟来安装和构建所有依赖项。
如此大量的引导和构建时间降低了开发者的体验,也浪费了众多优秀人才的时间。作为一个贡献者数量不断增长的开源项目,这种情况是不可接受的。
调试最慢的任务
检查典型的 12 分钟 GitHub 操作,很明显两个特定步骤占用了总时间的近 70-80%:
- yarn install - 需要 5-6 分钟
- yarn build:{package} - 可能需要 3-6 分钟来构建选定的包及其依赖项。
从 yarn 工作区迁移到 PNPM
PNPM 是一种快速、节省磁盘空间的包管理器(如其网站所述),并且从一些基准测试来看,安装时间有了很大的改善yarn workspaces
。
从那之后yarn install
大约花了 6 分钟,迁移到 pnpm 毫不费力:只需pnpm-workspace.yaml
在项目根目录下添加一个并运行pnpm install
,仅此而已。我们高效地安装了每个软件包的符号链接和依赖项,只需……等等……1.5 分钟!而且完全没有缓存!PNPM 缓存了大部分依赖项后,从缓存存储中构建和安装依赖项只需不到 40 秒。
对于首次贡献者来说,每次 CI 运行的启动时间以及本地启动时间都减少了约 4 分钟,这是一个巨大的进步。不过,等等,我们还可以做得更好。
从 Lerna 到 NX.dev
在看过vercel 的Turborepo 演示后,我对他们的分布式缓存机制很感兴趣。有了这种机制,我们可以重用其他维护者已经构建好的包,并下载dist
资源,而不必每次都重新构建它们。
turborepo与nx.dev哪个好?
经过简短的研究,我们决定选择 nx.dev,原因如下:
- 成熟度——nx 已经在市场上存在了一段时间,并且他们周围有一个相当大的社区。
- 性能- 从一些基准测试来看,nx 总体上看起来像是一个更快的构建系统。
我们的社区成员nishit-g接手了 GitHub 上的公开问题,并在我们提交 PR 后不久,结果令我们大吃一惊:构建步骤只需 30 秒!(而之前构建一组特定的软件包则需要 3-6 分钟)。
在部署 nx.cloud 进行分布式缓存后,在完全缓存构建的情况下,全部 24 个包的耗时不到5 秒。即使没有完全缓存,由于 nx 的智能并行机制,我们也能用不到30 秒的时间构建目标包。
概括
将构建时间从 12 分钟以上缩短到 3 分钟左右,显著提升了维护人员的开发体验。此外,它还缩短了从创建 PR 到运行测试套件再到合并功能的反馈循环。
非常感谢nishit-g帮助我们从 Lerna 迁移到 NX。也欢迎关注他的Twitter !
您可以在我们的GitHub 存储库上检查最终配置。
文章来源:https://dev.to/novu/how-we-reduced-our-nodejs-monorepo-build-time-by-70-3oma