Vue.js 3.0 源码管理用的Lerna
现在,许多工具能够在20个不一样的文件夹中运行“npm install”和“npm run build”。可是,并非全部的工具都能促进正确的monorepo。vue
促进一个正确的单体开发意味着要解决一些挑战,好比为分离的模块运行测试和构建过程,可以从项目中独立发布模块,以及管理变动对项目中每一个受影响的依赖模块的部分影响。node
挑战的清单还在继续,甚至包括“琐碎”的事情,好比你如何管理issues和PRs,这可能会随着你的开发规模而变得困难。react
请注意, 一个monorepo不是一个总体的应用程序(!) ——它不是一次性构建或部署的,它是一组单独开发的应用程序。
国庆期间10月5日尤大公开了vue3.0已完成的源码,也是采用了monorepo管理模式,看来monorepo确实有其独到的优点。webpack
monorepo是一种将多个package放在一个repo中的代码管理模式,摒弃了传统的多个package多个repo的模式。git
目前 Babel, React, Angular, Ember, Meteor, Jest等许多开源项目都使用该种模式来管理代码。github
解决的问题web
带来的问题npm
还不知道monorpo的同窗能够阅读如下文章:json
在这篇综述中,我收集了一些世界上最好的工具来构建一个“monorepo”,你能够在一个项目里面构建多个模块,而且有不错的开发者体验,能够扩展。bootstrap
这个列表并无进行排名,旨在根据每一个工具的优势来概述其优点。但愿能帮助你节省时间,找到合适的工具。
欢迎在下方评论,分享本身的心得。
Yarn Workspaces 的目标是简化与monorepos的工做,以更明确的方式解决 yarn link
的一个主要用例。你的依赖关系能够连接在一块儿,这意味着你的工做空间能够相互依赖,同时老是使用最新的代码。这也是比 yarn link
更好的机制,由于它只影响你的工做空间树而不是你的整个系统。
Workspaces有助于解决一些问题,使其成为一个很好的单兵装备。
node_modules
,不须要在项目中的不一样包中重复或克隆依赖关系。所以,Yarn Workspaces是一个很是强大的组合,能够和列表中的几乎全部工具,特别是Bit、Nx和Lerna等工具一块儿使用,做为你的monorepo管理抽象的下层。
不过,你也能够直接用workspaces发布。当一个工做空间被打包到一个存档中时,它会动态地将任何 workspace:
依赖关系替换为一个包的版本,所以您能够将结果包发布到远程注册表,而无需运行中间步骤——消费者将可以像使用任何其余包同样使用发布的工做空间。太酷了!
参考阅读: 基于lerna和yarn workspace的monorepo工做流
Bit是用于构建模块化项目的下一代工具。这是一种新的、使人兴奋的单仓库方法,在这种方法中,由同一个项目(同一个Bit工做空间)管理的模块实际上分布在不一样的范围内,而不考虑仓库。
Bit让你以彻底解耦的方式拆分模块的开发,享受简单的、总体的开发体验来协调一切。
使用bit,你能够在你的项目中解耦组件,这样每一个组件都是独立开发、构建、测试和发布的。每一个组件都是使用特殊的环境进行开发和构建的,这些环境是可扩展和可重用的,这样你就能够快速定制和再次使用它们。
Bit的工做空间管理着项目中全部组件之间的关系。当你对任何组件进行更改时,Bit会单独构建和测试它,并将更改传播到依赖关系图中。
组件能够做为独立的包,批量发布到NPM和/或bit.dev平台,用于协做、消费和文档。
Bit的UI能够帮助你查看你的monorepo的开发状况。当你编写代码时,每一个组件都会被记录、测试、构建等,你能够经过实时反馈和热重载直观地看到正在发生的事情。
Bit提供了解耦的开发环境--可重用和可定制的模块,这些模块将独立组件整个生命周期所需的不一样服务配置和“捆绑”在一块儿,如编译、捆绑、测试、磨合、文档等。
掌握组件图——Bit定义、管理并帮助你利用项目中全部组件之间的关系。
图形驱动的构建——当您对某个组件进行更改时,Bit会自动检测依赖于它的其余组件,并“知道”只构建依赖组件的受影响的图形。
“图形驱动的构建”也意味着,万一一个组件被标记了新的发布版本(在被导出到Bit的云端以前),Bit不只会在每一个受影响的组件上运行构建,并且会确保给它们标记一个新的发布版本。
隔离的测试和构建——每一个组件都是在项目外部隔离地构建和测试的,所以您能够确切地看到更改的影响。
组件构建管道——您能够在可重用的管道中构建做业,该管道可应用于项目或全部项目中的全部组件。
批量发布——在Bit monorepo中开发的每一个组件均可以做为一个独立的包发布。Bit去掉了配置每一个组件的“package.json”和其余设置文件的全部开销。你要作的就是运行'bit tag',这样Bit就会自动给全部修改过的组件打上版本补丁(支持semver规则),而后批量发布修改。
可重复使用的文档模板——每一个组件都使用可重复使用和可定制的模板进行文档化,Bit为您自动完成大部分工做。用MDX工做?也许还能够添加一些可视化的例子?没问题。
独立渲染的组合——每一个组件都是彻底独立渲染的,彻底在项目以外渲染,渲染的视觉效果(在编写代码时热从新加载)成为每一个组件文档的一部分。
NX是一套先进的可扩展的开发工具,适用于monorepos,很是强调现代全栈Web技术。
NX的目标是经过CLI(带编辑器插件)提供总体的开发体验,并提供可控代码共享和一致代码生成的功能。它还提供了增量构建,所以它不会在你的每一次提交中重建和从新测试全部内容,从而加快构建时间。
有了Nx,你可使用你喜欢的框架,集成你可能已经在使用的现代工具。例如,NX可让你使用与Cypress、Jest、Typescript、Prettier和其余工具的开箱即用的集成。
NX团队还提供了NX云,经过云中的智能计算记忆和更快的构建来帮助使用NX的团队更快地交付。
Rush是由微软+开源的一个强大的monorepo基础设施,它的目的是帮助你在一个仓库中构建和发布许多包。
rush的一些主要功能包括一个单一的NPM安装(也能够和Yarn和pnpm一块儿使用),因此你能够将全部项目的全部依赖关系安装到一个共同的文件夹中,使用隔离的符号连接为每一个项目从新构建一个准确的“node_modules”文件夹。
这也有助于确保没有幻影依赖,因此你不会意外地导入一个在package.json中缺失的库,也不会在node_modules中发现10份lib的依赖重复。
自动本地连接意味着你全部的项目都会自动地相互创建符号连接,当你作了一个改变,你能够看到下游的效果,而不须要发布任何东西,也没有任何 npm link
的麻烦。
Rush独特的安装策略为你的全部项目生成一个快速安装的单一收缩/锁定文件。Rush会检测你的依赖关系图,并以正确的顺序构建你的项目,因此若是两个包之间没有直接的依赖关系,Rush会将它们做为单独的进程并行构建。
若是你只打算使用你的repo中的几个项目,Rush提供了子集和增量构建,因此 rush rebuild --to <project>
只对你的上游依赖进行干净的构建。在你作了修改以后,rush rebuild --from <project>
只对受影响的下游项目进行清理。而 rush build
则提供了强大的跨项目增量构建,Rush甚至能够经过分离项目的版原本处理循环依赖关系。
当你想发布的时候,Rush支持批量发布,因此它会检测哪些包有变化,自动跳转全部相关的版本号,并在每一个文件夹中运行 npm publish
。
Rush还有助于实施和执行发展政策。例如,当建立PR时,你能够要求开发人员提供受影响项目的主要/次要/补丁日志条目,这些条目随后将在发布时汇总到一个变动日志文件中。它还能够帮助你执行诸如发布前的审查、特定的依赖版本等东西。
Lerna(以多头野兽Hydra的家命名)是一个“用于管理带有多个包的JavaScript项目的工具”。
Lerna的建立是为了解决Babel的多包问题,以优化使用git和npm管理多包仓库的工做流程,它本质上是一种工具和脚本,能够有效地管理和发布许多独立版本的包在一个Git仓库中。
my-lerna-repo/ package.json packages/ package-1/ package.json package-2/ package.json
Lerna 的两个主要命令是 lerna bootstrap
和 lerna publish
。bootstrap
会将 repo 中的依赖关系链接在一块儿,publish
会帮助发布任何更新的包。
您可使用如下两种模式之一来管理项目:固定(Fixed)或独立(Independent)。
固定模式的Lerna项目是以单一的版本行来操做的,版本是保存在你的项目根目录下的 lerna.json
文件中的 version
键。当您运行 lerna publish
时,若是一个模块在上次发布后被更新,它将被更新到您发布的新版本。这是Babel目前使用的模式。
独立模式Lerna项目容许维护者相互独立地增长包的版本,每次发布时,你都会收到一个提示,提示你每个已经改变的软件包,以指定它是一个补丁,小的,大的或自定义的变化。独立模式可让你更具体地更新每一个包的版本,对于一组包来讲是有意义的。
“lerna.json”文件是一个匹配包含 package.json
的目录的globs列表,这也是lerna识别“叶子”包的方式(相对于管理整个repo的开发依赖和脚本)。例子:
{ "version": "1.1.3", "npmClient": "npm", "command": { "publish": { "ignoreChanges": ["ignored-file", "*.md"], "message": "chore(release): publish", "registry": "https://npm.pkg.github.com" }, "bootstrap": { "ignore": "component-*", "npmClientArgs": ["--no-package-lock"] } }, "packages": ["packages/*"] }
即便你不打算发布到NPM,Lerna仍然能够在monorepo中帮助管理版本管理和常见的开发任务。
谷歌推出了Bazel build system,它是一个相似于Make、Maven和Gradle的开源构建和测试工具,使用的是人类可读的高级构建语言。Bazel支持多种语言的项目,并为多种平台构建输出。它支持大型单一仓库中的大型代码库或跨多个仓库的大型代码库和大量用户。
Uber开发者使用Bazel来构建他们的Go monorepo。Uber用Go编写了大部分的后端服务和库,在2018年,这些服务和库都被概括到一个大型的Go monorepo中,如今有超过10万个文件。Bazel让这个项目得以扩展,缩短了构建时间,并支持其发展。
这是一个不错的小型开源项目,以Bazel做为演示: thundergolfer/example-bazel-monorepo
Bazel被设计成大规模工做,并支持跨分布式基础设施的增量密封构建,这是大型代码库所必需的。有了Bazel的远程缓存,构建服务器还能够共享它们的构建工件。Bazel缓存全部之前完成的工做,并跟踪对文件内容和构建命令的更改。只有在包或包的依赖关系发生更改时,才构建和测试包。
Bazel能够在Linux、macOS和Windows上运行。Bazel能够从同一个项目为多个平台构建二进制文件和可部署的包,包括桌面、服务器和移动设备。支持许多语言,你能够扩展Bazel来支持任何其余语言或框架。
Buck是一个鼓励建立由代码和资源组成的小型可重用模块的构建系统,支持不一样平台上的各类语言。
它是由Facebook开发和使用的,做为FB单体的官方构建系统,因为被Uber开发者等团队使用,大大缩短了构建时间,所以名声大噪。而AirbnbEng的团队则将构建速度提升了50%,将应用程序缩小了30%。
Buck被设计用来构建一个monorepo,而对monorepo设计的支持激发了Buck对cell和项目的支持。
Facebook的经验是,将全部的依赖关系维护在同一个版本库中,能够更容易地确保全部开发者拥有正确的代码版本,并简化了进行原子提交的过程。
Buck经常使用于Android和iOS开发。
2014年,Twitter推出了名为Pants的monorepo构建系统。今天,在v2版本上,Pants的目标是成为一个快速、可扩展的构建系统,以适应不断增加的代码库。目前,它的重点是Python,很快就会支持其余语言。
Pants使用细粒度的工做流,并将每一个工做单元与反作用隔离,所以能够利用全部可用的内核。Pant的一些最佳特性包括明确的依赖建模、细粒度的无效化、共享结果缓存、并发执行、远程执行,以及经过插件API的可扩展性和可定制性。
Pants引擎是用Rust写的,为的是性能。构建规则是用类型化的Python 3写的,为了熟悉和简单。该引擎的设计使得细粒度的无效化、并发性、密封性、缓存和远程执行天然发生,而无需规则做者的干预。
Please是一个跨语言的构建系统,强调高性能、可移植性、可扩展性和正确性。
请确保构建步骤是在本身的密封环境中执行的,只能访问被赋予权限的文件和env变量。增量构建意味着它只构建它须要的东西,它还提供了任务并行性,以及分布式缓存,以实现大规模的可靠和高性能的构建系统。
Please的目标也是专一于开发体验,因此你能够享受一个经常使用的CLI,并为使用自动完成的常见任务定义别名。
Please用Go编写,Please提供全部这些用户体验,没有运行时依赖。而且,没有须要处理太多配置的单个大工做区文件。
Oao并非列表中最成熟、最丰富、最容易使用的工具,但它仍是颇有趣。它是一个基于Yarn的,有意见的monorepo管理工具,p提供monorepo功能,如安装全部的依赖关系,添加/删除/升级子包的依赖关系,验证版本号,肯定更新的子包,一次性发布全部的东西,更新变动日志等。
Oao可让你在全部子包上运行命令或 package.json
脚本,串行或并行,可选择遵循反向依赖树。并且,它支持yarn workspaces,从总体上优化了monorepo依赖树,简化了bootstrap以及依赖的添加/升级/删除。
支持非单包发布:从oao’s的发布前检查、标签、版本选择、变动日志更新等方面受益,也能够在你的单包、非单包中使用。须要注意的是,Oao使用的是同步版本方案,因此在根级的 package.json
中配置了一个主版本,而子包也将与该版本同步。你能够在这里尝试一下。
Boltpkg旨在成为一个“超级功能JavaScript项目管理工具”。
Bolt在Yarn的基础上实现了workspaces的概念。Bolt CLI在很大程度上是Yarn CLI的替代品,你能够在任何Yarn项目中使用它。
咱们知道,workspaces是嵌套在一个更大的项目/repo中的,每一个workspaces均可以有本身的依赖关系,有本身的代码和脚本。workspaces也能够纳入子目录进行组织。
使用Bolt,你能够一次安装全部这些包的依赖关系(并且你能够作得很是很是快)。并且,当你从一个工做区指定一个依赖关系到另外一个工做区时,它将被连接到源代码。这样,当你去测试你的代码时,你全部的变化都会被一块儿测试。