单独NPM包
对于需要复用的组件和业务是强绑定的,使用npm,语义上不合适
git submodule/subtree
采用主项目+子项目结合方式
缺点:
-
本质上
submodule和主项目是两个不同的git repo,所以你需要为每个项目创建一套脚手架(代码规范,发布脚本什么的)。 -
submodule其实只是主项目保存了一个对子项目的依赖链接,说明了当前版本的主项目依赖哪个版本的子项目,你需要小心的使用git submodule update来管理这种依赖关系。如果没有正确使用git submodule update而搞乱了版本的依赖关系,那就呵呵了。。。 -
发布的时候需要自己小心处理依赖关系,先发子项目,子项目好了再发布主项目。
搭建monorepo项目
- lerna(不在维护了)
- yarn+workspace
- pnpm
pnpm
用软链接和硬链接的方式不仅提高了安装速度还节约了磁盘空间,同时避免了依赖重复安装和幽灵依赖和node_modules下的扁平结构包版本的不稳定问题。 juejin.cn/post/714235…
为什么速度快
- 减少依赖重复,io更少
- 硬链接
mono-repo
对于 git submodule,主项目和子项目都是单独的git仓库,也就构成了多个仓库。
而mono-repo就是一个大仓库,多个项目都放在一个git仓库里面。现在很多知名开源项目都是采用的mono-repo的组织方式,比如Babel,React ,Jest, create-react-app, react-router等等。mono-repo特别适合联系紧密的多个项目。
"dependencies": { "@vueapps/utils": "workspace:^1.0.0" }
import { getAge } from "@vueapps/utils/getAge";
const age = getAge(); 、
console.log(age); //26
mono-repo侧重项目组织方式,webpack MF侧重微前端
-
事情的起源是我们接到了一个外国人交水电费并能卖东西的需求,有柜员端和客户自助端。
-
经过分析,我们决定将柜员端和客户自助端部署为两个站点。
-
为了这两个站点,我们新建了两个项目,这样扩展性更好。
-
这两个项目有很多长得一样的业务组件,我们需要复用他们。
-
为了复用这些业务组件,我们引入了
mono-repo的架构来进行项目管理,mono-repo特别适合联系紧密的多个项目。 -
mono-repo最出名的工具是lerna。 -
lerna可以自动管理各个项目之间的依赖以及node_modules。 -
使用
lerna bootstrap --hoist可以将子项目的node_modules提升到顶层,解决node_modules重复的问题。 -
但是
lerna bootstrap --hoist在提升时如果遇到各个子项目引用的依赖版本不一致,会提升使用最多的版本,从而导致少数派那个找不到正确的依赖,发生错误。 -
为了解决提升时版本冲突的问题,我们引入了
yarn workspace,他也会提升用的最多的版本,但是会为少数派保留自己的依赖在自己的node_modules下面。 -
我们示例中两个CRA项目都有自己的脚手架,而
common没有脚手架,我们调整了脚手架,将它挪到了最顶层,从而三个项目可以共享。 -
发布的时候使用
lerna publish,他会自动更新内部依赖,并更新各个子项目自己的版本号。 -
子项目的版本号规则可以在
lerna.json里面配置,如果配置为固定版本号,则各个子项目保持一致的版本,如果配置为independent关键字,各个子项目可以有自己不同的版本号。