前端工程化之MonoRepo架构

168 阅读4分钟

什么是MonoRepo

Monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。Monorepo 提倡了开放、透明、共享的组织文化,这种方法已经被很多大型公司广泛使用,如 Google、Facebook 和 Microsoft 等。

项目架构演进

阶段一:单仓库巨石应用, 一个 Git 仓库维护着项目代码,随着迭代业务复杂度的提升,项目代码会变得越来越多,越来越复杂,大量代码构建效率也会降低,最终导致了单体巨石应用,这种代码管理方式称之为 Monolith。

阶段二:多仓库多模块应用,于是将项目拆解成多个业务模块,并在多个 Git 仓库管理,模块解耦,降低了巨石应用的复杂度,每个模块都可以独立编码、测试、发版,代码管理变得简化,构建效率也得以提升,这种代码管理方式称之为 MultiRepo。

阶段三:单仓库多模块应用,随着业务复杂度的提升,模块仓库越来越多,MultiRepo这种方式虽然从业务上解耦了,但增加了项目工程管理的难度,随着模块仓库达到一定数量级,会有几个问题:跨仓库代码难共享;分散在单仓库的模块依赖管理复杂(底层模块升级后,其他上层依赖需要及时更新,否则有问题);增加了构建耗时。于是将多个项目集成到一个仓库下,共享工程配置,同时又快捷地共享模块代码,成为趋势,这种代码管理方式称之为 MonoRepo。

img

MonoRepo的优缺点

场景MultiRepoMonoRepo
代码可见性✅ 代码隔离,研发者只需关注自己负责的仓库 ❌ 包管理按照各自owner划分,当出现问题时,需要到依赖包中进行判断并解决。✅ 一个仓库中多个相关项目,很容易看到整个代码库的变化趋势,更好的团队协作。 ❌ 增加了非owner改动代码的风险
依赖管理❌ 多个仓库都有自己的 node_modules,存在依赖重复安装情况,占用磁盘内存大。✅ 多项目代码都在一个仓库中,相同版本依赖提升到顶层只安装一次,节省磁盘内存,
代码权限✅ 各项目单独仓库,不会出现代码被误改的情况,单个项目出现问题不会影响其他项目。❌ 多个项目代码都在一个仓库中,没有项目粒度的权限管控,一个项目出问题,可能影响所有项目。
开发迭代✅ 仓库体积小,模块划分清晰,可维护性强。 ❌ 多仓库来回切换(编辑器及命令行),项目多的话效率很低。多仓库见存在依赖时,需要手动 npm link,操作繁琐。 ❌ 依赖管理不便,多个依赖可能在多个仓库中存在不同版本,重复安装,npm link 时不同项目的依赖会存在冲突。✅ 多个项目都在一个仓库中,可看到相关项目全貌,编码非常方便。 ✅ 代码复用高,方便进行代码重构。 ❌ 多项目在一个仓库中,代码体积多大几个 G,git clone时间较长。 ✅ 依赖调试方便,依赖包迭代场景下,借助工具自动 npm link,直接使用最新版本依赖,简化了操作流程。
工程配置❌ 各项目构建、打包、代码校验都各自维护,不一致时会导致代码差异或构建差异。✅ 多项目在一个仓库,工程配置一致,代码质量标准及风格也很容易一致。
构建部署❌ 多个项目间存在依赖,部署时需要手动到不同的仓库根据先后顺序去修改版本及进行部署,操作繁琐效率低。✅ 构建性 Monorepo 工具可以配置依赖项目的构建优先级,可以实现一次命令完成所有的部署。

小型项目实践 pnpm+workspace 改造

改造前巨石项目架构

├─README.md
├─questionnaire-mock
|         ├─index.js
|         ├─package.json
|         ├─pnpm-lock.yaml
|         ├─mock
|         |  ├─index.js
|         |  ├─module
|         |  |   ├─question.js
|         |  |   └test.js
|         |  ├─data
|         |  |  └getQuestionList.js
├─questionnaire-fe
|        ├─.babelrc
|        ├─.eslintrc.js
|        ├─.prettierrc.js
|        ├─README.md
|        ├─commitlint.config.js
|        ├─craco.config.js
|        ├─package-lock.json
|        ├─package.json
|        ├─pnpm-lock.yaml
|        ├─tsconfig.json
|        ├─src
|        ├─public
|        |   ├─favicon.ico
|        |   ├─index.html
|        |   └manifest.json
|        ├─.husky
|        |   ├─commit-msg
|        |   └pre-commit

改造后MonoRepo项目架构

├─README.md
├─package.json
├─pnpm-lock.yaml
├─pnpm-workspace.yaml
├─packages
| ├─questionnaire-mock
| | ├─index.js
| | ├─package.json
| | ├─pnpm-lock.yaml
| | ├─mock
| | | ├─index.js
| | | ├─module
| | | | ├─question.js
| | | | └test.js
| | | ├─data
| | | | └getQuestionList.js
| ├─questionnaire-fe
| | ├─.babelrc
| | ├─.eslintrc.js
| | ├─.prettierrc.js
| | ├─README.md
| | ├─commitlint.config.js
| | ├─craco.config.js
| | ├─package-lock.json
| | ├─package.json
| | ├─pnpm-lock.yaml
| | ├─tsconfig.json
| | ├─src
| | ├─public
| | | ├─favicon.ico
| | | ├─index.html
| | | └manifest.json

改造的项目地址:gitee.com/IndulgeBack/react-questionnaire

文献参考

juejin.cn/post/721588…