Monorepo
2022-7-28 02:24:54 Author: taxodium.ink(查看原文) 阅读量:15 收藏

Contents

[NOTE] Updated May 31, 2023. This article may have outdated content or subject matter.

当项目变得庞大的时候,自然就会想到去拆分,以更小的单位去维护,或者复用。

一种组织方式是,将项目拆成多个独立的 repo,然后通过子模块关联,

或者将某些模块发到 npm,通过 npm 去安装依赖。

这种拆分成多个 repo 的组织形式,称为 multirepo ,这种组织形式的有什么优劣呢?

multirepo 优缺点

优点

  • 每个仓库的大小一般不会很大

  • 每个仓库独立,可以单独对仓库进行权限控制, 例如控制谁有权限访问,谁可以提交等。

缺点

  • 当维护多个 repo 时,需要在多个 repo 之间切换,容易混乱。

  • 每个仓库可能有一套自己的配置,仓库之间不兼容,标准不统一。

  • repo 和子模块可能存在重复的依赖,导致依赖的重复安装。

  • 不在同一个 repo 中,不方便分析整个项目的所有依赖。

  • 发布的时候,如果多个 repo 存在依赖关系,要按照依赖顺序依次构建再部署。

  • repo 之间存在依赖关系,调试依赖的仓库时,需要 npm link 关联仓库。

面对 multirepo 的这些问题,就有人提出了 monorepo 的组织方式。

A monorepo is a single repository containing multiple distinct projects, with well-defined relationships.

一个 monorepo 应该是:

  • 单一的仓库

  • 仓库中包含多个独立的项目

  • 每个项目之间的关系定义清晰明确

简单的理解,monorepo 就是把原来的 multirepo 合并成一个 repo。

那是不是把每个 repo 分别放到不同的目录,建一个新的庞大的仓库,就完事了呢?

这样就变成一个“大杂烩”了,被称为 Single-repo Monolith, 已经接近 monorepo 的样子了。

在这个基础上,还需要:

  1. 每个 repo 逻辑上独立,项目之间可能是不相关的,松散连接的,或者可以通过一些方式连接起来。(譬如 pnpm 的 workspace)

  2. 要保证项目之间的依赖关系定义清晰

    • 项目间的依赖关系
      项目之间存在依赖时,不需要人工按照拓扑排序进行 link,
      而是有一定程度的自动化,通过一些简单的配置,可以自动完成 link。
      例如每个项目配置好 package.json, 定义依赖关系,然后自动分析 package.json,自动完成项目之间的关联

    • 项目第三方依赖间的关系
      多个项目中,相同的依赖应该只安装一次;
      版本不同的依赖需要解决好冲突,例如一些对单例有要求的依赖(react)

    对于 项目间的依赖关系 ,为了实现一定程度的自动化,需要借助一些工具,如 NXLernaturborepo

    对于 项目第三方依赖间的关系, 可以借助 yarnpnpm 等包管理工具的 workspace 功能去实现。

    所以,有别于 Single-repo Monolisth, monorepo 需要有明确清晰的依赖关系,能够很方便地管理依赖。

优点

  • 更容易管理依赖

  • 源码都在一起,方便调试

  • 可以在多个模块中,复用相同的配置,例如单元测试,CI/CD 相关的配置,便于保持规范一致

  • 由于相关的项目都在一起,因此可以比较方便地编写集成测试

  • 当有一个功能,牵涉多个模块时,可以在一个提交中改好,而 multirepo 则需要在多个 repo 做提交

缺点

  • 项目启动,打包构建速度变慢

  • 当项目很庞大,提交记录很多时,git 的一些操作性能上会变慢

  • 没法限制不同模块的访问权限。也是一个优点,开发人员能看到所有模块,了解到这些模块的关联,而不是只关注自己的模块。

  • 可能出现"幽灵"依赖,由于依赖安装在项目的 root 目录,所有模块能访问到, 于是即使模块中忘了声明某个依赖,但是 root 中存在,则可以使用。但实 际部署时,会因为没有声明依赖,导致没有安装而报错。

  • Monorepos By Example: Part 1
    一个应用 monorepo 的例子。用 Lerna 管理依赖。

  • Spike-Leung/leetcode
    我自己的实践,分成了 solutions, solution-parser, web 三个 package, 然后用 pnpm 的 workspace 关联,比较简单,没用到 monorepo 的工具。

  • illa-design
    一个组件库,组件之间就是以 monorepo 的形式组织的,目前 使用的工具是 turborepo

  • vuejs/core
    看起来也是一个 monorepo 的组织方式,使用了 pnpm 去管理依赖

Author Spike Leung

LastMod 2023-05-31 (1ef6a30)

License CC BY-NC-ND 4.0


文章来源: https://taxodium.ink/post/monorepo/
如有侵权请联系:admin#unsafe.sh