专题归档 · 2026 年 3 月(编辑分组,非实际写作日期)
第一次跟着 Nx Demo 建 Monorepo:zoo 为什么会先构建 animal?
记录官方 Nx 教程的两个 Package、依赖图和受影响构建的第一次理解。
刚开始接触 Nx 时,我对 Monorepo 的理解更多是“把多个项目放进同一个 Git 仓库”。跟着官方 TypeScript Packages 教程做了一个简单示例后,我才开始留意:真正要管理的是项目之间的依赖与任务执行顺序。
从目录结构开始
最初的工作区有 nx.json、根 package.json、tsconfig,以及用来存放子包的 packages/。教程示例里,我尝试理解两个包的依赖关系:
zoo → animal
也就是说,zoo 的代码会导入 animal 提供的东西;依赖由包清单和项目配置表达,而不需要人在心里记住“每次构建 zoo 前先构建 animal”。
教程里的包依赖大致是这样:
{
"dependencies": {
"@acme/animal": "*"
}
}
这里的包名和版本范围只是教学示例,实际工作区还要由相应 Package Manager 的 workspace 配置来解析。
第一个重要观察:build zoo 会牵涉 animal
我当时记录的关键命令是:
npx nx build zoo
理解的转折是:Nx 可以根据项目依赖关系和目标配置,先执行依赖项目所需的构建,再处理当前的 zoo。这背后的项目图不仅为构建服务,也能让测试、缓存和影响范围分析有确定依据。
不过有必要澄清:并非任何 Nx 工作区、任何 build Target 都必定自动“先构建依赖”。这取决于 dependsOn、targetDefaults、插件的推断配置和版本。我在教程里看到的是一种特定配置下的依赖构建效果,不意味着所有 Nx 项目都会自动这样执行。
为什么它与我自己的项目有关
当时我已经开始用 Monorepo 管理带业务模块的项目。过去比较容易把“共享一个 Repo”和“项目之间有稳定的构建契约”混为一谈。
这次练习让我意识到一个问题:如果一个模块依赖另一个模块,那么 TypeScript Path、Package 名称、任务执行依赖、发布产物之间需要一致。否则本机因为历史缓存能运行,干净 CI 却可能解析不到预期的 Workspace 包。
这个问题后来在 DailyUse 的一次真实 CI 排障中再次出现,另有 独立排障记录。两篇不要混成同一次事件:这篇是跟教程学习项目图,后者是实际 CI 失败。
这次 Demo 没有证明什么
旧 Note 留了目录结构、命令和一张截图,但没有完整版本锁、冷缓存构建日志或自定义插件配置。因此它是一篇第一次认识工具的随记,而不是一个可复制即保证成功的生产级模板。
至少我开始明白:Monorepo 的核心价值不只是放在一起,而是让依赖关系和任务次序可计算。