Rush Stack商店博客活动
跳至主要内容

为什么选择一个大型仓库?

开源 NPM 包似乎是在很多小的 GitHub 仓库中开发的。我不应该这样做吗?

当然,如果你正在构建孤立的组件,并且它们如何组合在一起并不重要。但商业软件似乎并非如此。更像是这样

大多数人一开始都是构建单个 Web 应用程序,而不是一堆库。你的应用程序发布后,它会不断增长。然后有一天,你需要与另一个项目共享一些代码,你会意识到自己陷入了一个巨大的乱七八糟的局面。是时候重构了!

显然,你必须将它拆分成可管理的组件。NPM 包是 JavaScript 中实现此目的的方式。四处看看,惯例似乎是“每个 NPM 包一个 GitHub 仓库”。在一个英雄般的两周时间里,你创建了 10 个 Git 仓库,拆分了你的代码,并试着运行它...

...但使用 10 个 Git 仓库事实证明是一件很痛苦的事情!有很多头疼的事情

  • 隧道视野:如果同事主要在仓库 #5 和 #6 中工作,他们似乎完全忽略了其他 8 个仓库的拉取请求。每天都会出现新的仓库,你甚至不知道它们的存在。

  • 级联发布:将修复从lib3传播到你的应用程序项目需要以正确的顺序更新/构建/发布多个 Git 仓库:lib3 --> lib2 --> lib1 --> application。当lib3频繁发生变化时,这将变得非常乏味。人们怎么会记得发布的正确顺序?互联网有很多人可以处理这个问题,但你的人手有限,而且他们非常忙。

  • 下游受害者:当 Bob 发布对lib3的更改时,可能需要一段时间才能将所有下游项目升级以使用它。如果存在回归,可能需要一周的时间 Alice 才会尝试在lib1中运行“npm update”并发现问题。到那时,Bob 可能已经去欧洲背包旅行了。为什么 Alice 应该承担修复别人回归的负担?似乎每次她升级,都会出现问题!

  • 链接疯狂:解决方法是使用npm link将你的application直接链接到lib3进行测试。但 NPM 通过全局文件夹创建符号链接,如果你需要在同一台笔记本电脑上使用lib3的多个分支,这会导致问题。而使用 10 多个库时,很难记住哪些链接到什么。

“每个包一个仓库”模型适用于由不协调的陌生人维护的孤立项目。(此外,大多数这些库的更新频率较低,这使得问题更容易解决。)而在我们的示例中,每个人都在同一家公司工作,“库”更像是集成架构的组件。代码经常发生变化,一个地方的更改很容易破坏系统的其他部分。一起构建多个项目可以让你在每次更改时运行所有单元测试,这将把修复责任放到它应该在的地方:最初引入更改的人那里。

出现的原则变成了“每个团队一个 Git 仓库”,或者更好的是“尽可能少地使用 Git 仓库来完成工作”

monorepo block diagram

很多 构建大型商业软件似乎最终都将所有代码放在一个大型的“monorepo”中。JavaScript 只是最后一个加入聚会的人。

这种策略的重大问题显然是构建时间。JavaScript 工具比编译语言慢。如果一个项目需要 1 分钟才能构建,而你有 75 个项目,理论上你可能需要漫长的 75 分钟的构建时间。这似乎令人望而生畏,但使用工业级强度的工具链,你可以扩展到很远,直到构建时间成为问题。Rush 和 Heft 的大部分路线图都集中在构建时间上,我们乐观地认为,优化空间仍然很大。使用子集/增量构建,理论上你可以避免重建所有内容,除非更改确实影响了所有内容——而对于这种类型的更改,很难争辩说尽早发现错误不值得等待更长的构建时间。