Rush StackShopBlogEvents
跳到主要内容

与Rush的接口

Hello World教程演示了如何在独立项目中使用 Heft。现在,让我们来看看 Heft 在 Rush monorepo 环境中是如何工作的。

Heft 如何被调用

如果你对 Rush 不熟悉,维护者教程解释了设置新 repo 的基础知识。当 Rush 在 Rush 项目文件夹中调用"build"脚本时,Heft 开始接管。在我们的教程样本项目中,脚本看起来是这样的:

<项目文件夹>/package.json

{
. . .
"scripts": {
"build": "heft build --clean",
"start": "node lib/start.js"
}
. . .
}

使用 rig package 共享配置

在 monorepos 中的一个主题将是最小化"样板"文件。换句话说,整合那些否则会复制+粘贴到 monorepo 的每个项目文件夹中的文件和设置。样板是一种麻烦,因为它很难保持同步。当需要修复时,如果你有数百个项目,你需要重新应用相同的修复数百次。(更糟的是,如果允许工程师以不同的方式定制他们的项目,那么你可能需要应用数百个不同的修复,这是非常高的维护成本。)

与此同时,我们希望尊重 Rush 的项目隔离原则:每个项目应独立构建,不应与其他项目纠缠在一起(例如,通过使用相对路径如../../other-project引用文件)。这种纪律促进了 Rush 的特性,如子集构建和增量构建。这也使得在 monorepos 之间迁移项目,甚至如果你改变主意后停止使用 Rush,移动 Rush 项目文件夹变得非常容易。因此,我们不鼓励如在 monorepo 的根目录中放置一个集中的.eslintrc.js文件,并为所有项目全局调用 ESLint 的做法。

结合这些目标,Heft 支持一种叫做rig package的正式概念,其中共享的设置由添加到每个项目的devDependencies的 NPM package 提供。rig package 提供三种减少重复的方式:

  1. 配置文件可以使用"extends"等设置继承 rig 的常用设置。例如:tsconfig.json
  2. Riggable 配置文件可以完全被消除,使用config/rig.json文件指导 Heft 在 rig package 中找到它们。例如:config/heft.json
  3. Riggable 依赖项可以由 rig package 提供,避免需要将它们添加到你的项目的devDependencies。例如:typescript package

使用 rig package文章详细描述了这个。

增量构建

使用 Rush 与 Heft 的另一个好处是支持增量构建。例如,如果你运行rush build两次,第二次它将立即完成,因为所有的项目都已经构建过了。有趣的是,这个增量构建分析是由 Rush 自己执行的,而不是 Heft。

由于 JavaScript 是一种解释型语言,每次在项目文件夹中启动一个 Node.js 进程都会有一点开销。因此,即使 Heft 完全不执行任何工作,它也可能需要 1 秒钟的时间来启动工具链,分析输入文件,并确定一切都是最新的。对于拥有 500 个项目的 monorepo 来说,这加起来就是 500 秒的分析时间。Rush 通过对所有项目进行全局分析,比较你的源文件的 hash 和输出文件的 hash 来避免这个。如果这些 hash 是相同的,那么 Rush 就可以确定一个项目可以完全跳过,甚至不用启动 Heft。Rush 的增量构建分析适用于任何规范的脚本,不仅仅是 Heft。

使用 Heft phases 实现 Rush phases

Rush 的增量构建可以使用Rush phases进行更粒度的划分。 Heft phases 专门设计用来与这个模型对齐。

下面是从 GitHub 上的 Rush Stack monorepo 中的node-core-library/package.json摘录的一部分:

  "scripts": {
"build": "heft build --clean",
"test": "heft test --clean",
"_phase:build": "heft run --only build -- --clean",
"_phase:test": "heft run --only test -- --clean"
},

"test"命令调用heft test,它将执行buildtest两个 phases,而"_phase:test"命令只执行test phase。这是可行的,因为config/rush/command-line.json模型化了我们的 phase 依赖,所以 Rush 本身将确保在执行test之前运行build phase。通过向 Rush 公开这些细节,Heft 的 phases 可以使用 Rush 的构建缓存进行优化,甚至可以参与到使用 Cobuild feature 的分布式构建中。