最近在开发脚手架的时候参考了 vue-cli 的源码,发现它采用了 monorepo 的方式去管理项目,刚好前段时间看过一点 vue 的源码,也是用的 monorepo,由此引发了我的思考,于是便探究一下使用 monorepo 的原因。
一. monorepo 是什么
monorepo
是工程项目的一种管理方式, 它将关联性较强的项目放在一个 repository 中共同管理,以下就是使用 monorepo
管理后的项目目录结构
.
├── .git
├── node_modules
├── package.json
└── packages
├── package-a
| ├── src
│ └── package.json
├── package-b
| ├── src
│ └── package.json
└── package-c
├── src
└── package.json
另外一种比较常见的管理方式是将每一个项目都单独设置一个 git repository,这种方式也被称为multirepo
,下面这种就是经典的 multirepo
管理方式
.
├── package-a
├── .git
├── node_modules
├── src
└── package.json
.
├── package-b
├── .git
├── node_modules
├── src
└── package.json
.
├── package-c
├── .git
├── node_modules
├── src
└── package.json
本文所要探讨的 vue 和 vue-cli 都是使用 monorepo 管理项目
二. monorepo vs multirepo
在学习或者引入一门新技术之前,一定要明确它的存在是为了解决什么问题,绝大部分的技术都是基于现有的问题而提出的改进方案,我们只有明确其背景、原因,才能更好的判断一项技术适用于什么场景,怎么去使用
不管是 monorepo 还是 multirepo,都是为了解决项目管理的问题,所以最主要的问题是:**it项目管理中需要解决哪些问题?**例如模块依赖、团队协作等。
但是由于笔者工作经验较少,对于这方面没有很深的体会,因此只能通过查阅相关资料的方式简单做一些总结。
1. 依赖管理
使用 monorepo 能更好的管理本地的模块之间相互依赖关系
假如有 A, B, C, D 四个项目,A作为一个基础库支撑 B, C, D 四个项目,当 A 在开发新功能 / 对现有功能进行修改的时候,可以很容易的看出来其改动对 B, C, D 项目的影响,从而更好的进行权衡
在 multirepo 下,每个模块的联系并不紧密,改动 A 的话并不能直观看出影响,必须等到发布后才能判断
当然也可以使用npm link
的方式链接本地依赖,但是如果项目比较大就是个灾难...
另外,在 monorepo 模式下可以借助工具很方便的进行统一的依赖升级,在前端开发中也不用安装多次 node_modules,大大减少了磁盘占用空间和安装时间
2. 代码复用
在 monorepo 模式下,如果在开发过程中想抽取可复用的代码是十分简单的事情,只需要在原有的如 utils
模块下添加代码,或者重新开一个模块就可以了
对于 multirepo 来说,跨项目的公共代码实现是比较麻烦的,虽然可以通过发布包安装依赖的方式解决这个问题,但是始终没有 monorepo 来的方便
3. 团队协作
monorepo 的管理方式可以让团队的协作更加紧密,使得团队成员站在更高的视角上去开发。
还是上面那个 A, B, C, D 例子,如果 A 模块有新的 API 变动,在修改完提交后, D 模块如果由于 API 的变动导致应用无法运行,那么自然会当面找 A 模块的开发人员协作(笑)
这也使得A模块在开发新功能、修改现有功能的时候不得不考虑到全局的运作情况
三. 管中窥豹 -- 简析 vue 的 monorepo
vue 在 3.0 版本之前一直使用的单个仓库,但是在 3.0 以后就改为了 monorepo 的管理方式,自然也带来了一些好处
1. 模块独立
以下为 vue 的 package 目录:
.
├── compiler-core
├── compiler-dom
├── compiler-sfc
├── compiler-ssr
├── global.d.ts
├── reactivity
├── runtime-core
├── runtime-dom
├── runtime-test
├── server-renderer
├── shared
├── size-check
├── template-explorer
└── vue
在 vue 3.0 中有个重大的能力变化就是更灵活的支持跨平台渲染,只需要自己实现一个渲染器就可以在不同的平台上渲染,这也在一定程度上依赖了 monorepo 的管理方式,将 runtime-dom
与 runtime-core
解耦,需要的时候我们完全可以只引入 @vue/runtime-core
包来实现自定义渲染
同样如果只想使用响应式部分,完全可以只引入 @vue/reactivity
2. 代码复用
在 vue 的开发过程中存在很多通用的工具 / 方法,使用 monorepo 的方式能更好的抽离代码到shared-utils
模块中
3. 模块联系紧密
由于这些模块都是为了 vue 本身而服务,因此模块间的依赖是比较紧密的。
例如runtime-core
中依赖了reactivity
, shared-utils
模块又被大部分模块所引用,所以使用 monorepo 而不是 multirepo 的方式可以更好的管理模块间的依赖
在开发的时候可以很清楚的看出一个模块的改动会不会给其他模块带来影响
三. 总结
如果你的项目有下面几个需求:
- 代码复用需求强
- 团队协作需要紧密
- 模块间依赖程度较强
那么我觉得不妨试一试 monorepo 的策略
不过 monorepo 或者是其他的什么管理方式并不能说绝对的好或者绝对的坏,在适用的场景下发挥其最大的能力才是正解。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!