开源NPM包貌似是分散在很多小的Github仓库中的。我是不是也应该这么搞?
如果你写的组件彼此没啥关系,这么做没毛病。但是商业软件不能这么干:
其实绝大多数人的工作都是搞Web应用,而不是写library。当你写的应用越来越大。某天你想将其中的一些代码用于其他项目时,你会对着你的代码:“这TM是啥啊?是啥啊?(电音)”好吧,重构吧。
显然,你得把代码分割为可管理的组件。JS世界里,就是NPM包。你调研了一圈儿发现,不就是每个NPM包弄一个Github仓库么。哐哧哐哧俩礼拜,你搞了10个Git仓库...
但是,10个仓库啊,疯了:
-
管中窥豹:如果某个同事大部分时间都在开发5号、6号仓库。他们大概率会完全忽略8号仓库的PR。并且新仓库被创建的时候,你可能压根就不知道。
-
级联发布:当lib723修复bug后需要按正确顺序更新、构建、发布一系列相关的仓库才会被传导到你的应用中。比如lib723 → lib235 → lib331 → 你的应用。如果lib723频繁更新,那可就酸爽了。你能记住前面的发布顺序么?反正我不行。
-
影响下游:假设Bob修改了lib723并发布。可能得等很久使用lib723的工程才会去升级。如果不巧有个回退,可能要等一个礼拜,使用者Alice才会运行“npm update”并发现出了问题。到那个时候,Bob可能已经去欧洲背包行了。为毛Bob的回退要让Alice买单?每次她升级npm包都出问题。Alice:谢特!
-
link疯了:一个变通的解决办法是使用npm link将lib723软连接到你的应用中进行测试。但是NPM通过一个全局的文件夹创建软连接。而当你需要同时在一台电脑上使用lib723的多个版本就完蛋了。假设有10个包需要连接,疯了,谁记得住哪连哪儿啊。
对于彼此相对独立,维护者都不认识的工程,这种“一个包一个仓库”的做法没问题。(并且,大多数库更新并不频繁,所以问题不大)。但是在上面的例子里,开发人员是一个公司的同事。这些库更像是内部组件,并且代码三天两头的变。还一变就崩。这谁受得了啊。返过来,如果将多个工程放在一起,每次改动,都可以跑一下单元你测试。这样谁改了代码,谁就负责修复改动带来问题。这就很nice了。
逐渐较流行的组织代码的原则变成了 "一个团队,一个仓库",甚至是 "主要能搞定,仓库越少越好"。
貌似很多 的 大型软件的 开发者 最终都是选择了“Monorepo”。只不过JavaScript圈是最后才这么干的。
这种组织代码的原则最大的问题就是构建时间. JavaScript的相关工具比编译型语言的工具要慢。如果每个工程用1分钟构建,你有75个工程要构建。理论上需要75分钟!貌似不行啊,别急,通过使用NB的工具链可以解决这个问题。我们在设计Rush和gulp-core-build时,构建时间是着重考虑的。并且还有很大优化空间。通过“子集/增量”构建,理论上可以避免重新编译整个项目,除非发生的改变确实会影响所有内容。对于这种情况,完全构建还是有必要的。