Monorepo 介绍
一、Monorepo 介绍
Monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。Monorepo 提倡了开放、透明、共享的组织文化,这种方法已经被很多大型公司广泛使用,如 Google、Facebook 和 Microsoft 等。
二、Monorepo 演进
阶段一:单仓库巨石应用, 一个 Git 仓库维护着项目代码,随着迭代业务复杂度的提升,项目代码会变得越来越多,越来越复杂,大量代码构建效率也会降低,最终导致了单体巨石应用,这种代码管理方式称之为 Monolith。
阶段二:多仓库多模块应用,于是将项目拆解成多个业务模块,并在多个 Git 仓库管理,模块解耦,降低了巨石应用的复杂度,每个模块都可以独立编码、测试、发版,代码管理变得简化,构建效率也得以提升,这种代码管理方式称之为 MultiRepo。
阶段三:单仓库多模块应用,随着业务复杂度的提升,模块仓库越来越多,MultiRepo这种方式虽然从业务上解耦了,但增加了项目工程管理的难度,随着模块仓库达到一定数量级,会有几个问题:跨仓库代码难共享;分散在单仓库的模块依赖管理复杂(底层模块升级后,其他上层依赖需要及时更新,否则有问题);增加了构建耗时。于是将多个项目集成到一个仓库下,共享工程配置,同时又快捷地共享模块代码,成为趋势,这种代码管理方式称之为 MonoRepo。
三、Monorepo 优劣
场景 | MultiRepo | MonoRepo |
---|---|---|
代码可见性 | ? 代码隔离,研发者只需关注自己负责的仓库 ? 包管理按照各自owner划分,当出现问题时,需要到依赖包中进行判断并解决。 | ? 一个仓库中多个相关项目,很容易看到整个代码库的变化趋势,更好的团队协作。 ? 增加了非owner改动代码的风险 |
依赖管理 | ? 多个仓库都有自己的 node_modules,存在依赖重复安装情况,占用磁盘内存大。 | ? 多项目代码都在一个仓库中,相同版本依赖提升到顶层只安装一次,节省磁盘内存, |
代码权限 | ? 各项目单独仓库,不会出现代码被误改的情况,单个项目出现问题不会影响其他项目。 | ? 多个项目代码都在一个仓库中,没有项目粒度的权限管控,一个项目出问题,可能影响所有项目。 |
开发迭代 | ? 仓库体积小,模块划分清晰,可维护性强。 ? 多仓库来回切换(编辑器及命令行),项目多的话效率很低。多仓库见存在依赖时,需要手动? npm link ,操作繁琐。? 依赖管理不便,多个依赖可能在多个仓库中存在不同版本,重复安装,npm link 时不同项目的依赖会存在冲突。 | ? 多个项目都在一个仓库中,可看到相关项目全貌,编码非常方便。 ? 代码复用高,方便进行代码重构。 ? 多项目在一个仓库中,代码体积多大几个 G, git clone 时间较长。? 依赖调试方便,依赖包迭代场景下,借助工具自动 npm link,直接使用最新版本依赖,简化了操作流程。 |
工程配置 | ? 各项目构建、打包、代码校验都各自维护,不一致时会导致代码差异或构建差异。 | ? 多项目在一个仓库,工程配置一致,代码质量标准及风格也很容易一致。 |
构建部署 | ? 多个项目间存在依赖,部署时需要手动到不同的仓库根据先后顺序去修改版本及进行部署,操作繁琐效率低。 | ? 构建性 Monorepo 工具可以配置依赖项目的构建优先级,可以实现一次命令完成所有的部署。 |
四、Monorepo 场景
综合如上 Monorepo VS MultiRepo,中大型项目,多模块项目,更适合用 MonoRepo 方式管理代码,在开发、协作效率、代码一致性方面都能受益。
五、Monorepo 踩坑
5.1、幽灵依赖
问题:npm/yarn 安装依赖时,存在依赖提升,某个项目使用的依赖,并没有在其 package.json 中声明,也可以直接使用,这种现象称之为 “幽灵依赖”;随着项目迭代,这个依赖不再被其他项目使用,不再被安装,使用幽灵依赖的项目,会因为无法找到依赖而报错。
方案:基于 npm/yarn 的 Monorepo 方案,依然存在 “幽灵依赖” 问题,我们可以通过 pnpm 彻底解决这个问题
5.2、依赖安装耗时长
问题:MonoRepo 中每个项目都有自己的 package.json 依赖列表,随着 MonoRepo 中依赖总数的增长,每次 install 时,耗时会较长。
方案:相同版本依赖提升到 Monorepo 根目录下,减少冗余依赖安装;使用 pnpm 按需安装及依赖缓存。
5.3、构建打包耗时长
问题:多个项目构建任务存在依赖时,往往是串行构建 或 全量构建,导致构建时间较长
方案:增量构建,而非全量构建;也可以将串行构建,优化成并行构建。
六、Monorepo 选型
6.1、构建型 Monorepo 方案
此类工具,主要解决大仓库 Monorepo 构建效率低的问题。项目代码仓库越来越庞大,工作流(int、构建、单元测试、集成测试)也会越来越慢;这类工具,是专门针对这样的场景进行极致的性能优化。适用于包非常多、代码体积非常大的 Monorepo 项目。
6.1.1、Turborepo
Turborepo 是 Vercel 团队开源的高性能构建代码仓库系统,允许开发者使用不同的构建系统。
6.1.2、Rush
Rush?是微软开发的可扩展的 Monorepo 工具及解决方案。早期,只提供了 Rush 作为构建调取器,其余事项交给用户灵活的选择任意构建工具链,由于过于灵活带来了很大的选型及维护成本,后来成立了 Rush Stack 来提供了一套可复用的解决方案,涵盖多项目的构建、测试、打包和发布,实现了更强大的工作流。有如下工具:
- Rush: 可扩展的 monorepo 构建编排工具
- Heft: 可以与 Rush 交互的可扩展构建系统
- API Extractor: 为工具库审阅 API 并生成 .d.ts 文件
- API Documenter: 生成你的 API 文档站
- @rushstack/eslint-config: 专门为大型 TypeScript monorepo 仓库设计的 ESLint 规则集
- @rushstack/eslint-plugin-packlets: 可用于在单个项目内来组织代码,NPM 发包的一个轻量级解决方案
- Rundown: 用于优化 Node.js 启动时间的工具
6.1.3、Nx
Nx 是 Nrwl 团队开发的,同时在维护 Lerna,目前 Nx 可以与 Learn 5.1及以上集成使用
6.2、轻量化 Monorepo 方案
6.2.1、Lerna
6.2.2、yarn/npm + workspace
6.2.3、Lerna + pnpm + workspace
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!