Monorepo
Monorepo 是一个单一的存储库,包含多个不同的项目,和明确的关系。
能解决什么问题?
不仅仅在于减少了维护和管理多个代码库的成本,同时还有以下优点:
- 代码复用:因为多个项目共享一个代码库,所以避免了在不同项目中重复编写相同功能代码的问题,提高了开发效率。
- 提升协作效率:多个项目在同一个代码库中进行开发,可以方便地共享代码和文档,避免不同项目之间的沟通和协调成本。
- 集中管理:Monorepo 架构中,不同的应用程序都在同一个代码库中,方便管理和监控。这一点非常重要,特别是在需要同时对多个版本进行修改和维护的情况下。
- 统一构建:Monorepo 的一个重要特点是可以共用一套构建系统和工具链进行构建和部署,提升了构建的效率。
- 可以快速定位问题:由于所有的代码都在同一个代码库中进行开发,debugger 可以很快找出问题所在的代码文件和行数,便于开发人员调试问题。
- 一个版本:无需担心因为项目依赖于第三方库的冲突版本而导致的不兼容问题。
Monorepo 的基本组织方式如下
├── packages |
在 packages
目录下存放多个子项目,当然也可以叫其他名字,每个子项目都有自己的 package.json
文件,用来管理子包。
几种组织方式
不搭配微前端
公共组件,库,api 跟项目分离,将项目放到 packages
目录中
├── components |
请保证已安装 pnpm
, 随后执行如下命令
pnpm init |
项目根目录新建 pnpm-workspace.yaml
文件,注意要共享依赖的包,一定要在下面定义
packages: |
创建 packages
文件夹, 然后创建公共目录 比如 api
,components
等,跟 packages
文件夹同级
示栗:
mkdir api && cd api && pnpm init && pnpm add axios |
在 api
根目录下,创建对应的文件,进行封装和引用以及导出
比如,axios.ts
封装 api 代码 user.ts
是具体使用, index.ts
导出,注意,这里 index
是因为当前包的 package.json
文件 main
主入口文件 main
指向的就是 index.ts
文件
然后,定义子包的名称,建议 @目录名/api
,并且在 main
下面添加 private:true
代表私有的包
接着切换到对应的项目,在对应的项目使用公开的依赖包
pnpm add @cheny/api 注意,如果不行需要添加--workspace |
搭配微前端
目录结构组织方式如下参考:
├── apps |
其他部分
项目只允许 pnpm
来开发,可以在 package.json
中的 script
指定
"preinstall": "npx only-allow pnpm" |
设置 node
的基础版本
"engines": {"node":">=20"} |
子包设置发布,在子包 package.json
中
"publishConfig": {"access":"public"} |
包之间互相引用
pnpm -F @cheny/project1 add @cheny/test-api |
给某个包安装依赖
pnpm add axios --filter @qftjs/monorepo1 |
怎么进行相应的发布呢?
登录 npm,npn login
Changesets
changesets
主要关心 monorepo
项目下子项目版本的更新、changelog 文件生成、包的发布。一个 changeset 是个包含了在某个分支或者 commit
上改动信息的 md
文件,它会包含这样一些信息:
- 需要发布的包
- 包版本的更新层级(遵循 semver 规范)
- CHANGELOG 信息
changesets 的执行流程大概可以理解为:生成临时的 changelog → 消耗 changelog 生成组件的更新记录,并更新组件 version → 发布组件
changesets 的工作流程是这样:开发者在 monorepo
项目下进行开发,开发完成后,给对应的子项目添加一个 changesets
文件。项目的维护者后面会通过 changesets
来消耗掉这些文件并自动修改掉对应包的版本以及生成 CHANGELOG
文件,最后将对应的包发布出去。
安装,通过 changsets
管理包版本,需要将它安装到最外层的包根目录包
pnpm install @changesets/cli -w --save-dev |
初始化 changeset
在项目根目录下生成一个 .changeset
目录,里面会生成一个 changeset
的 config
文件。linked
字段改成你自己的包名
pnpm changeset init |
注意,👉 如果 config
中有个 access
,如果后面 npm 发版时,npm 报错 unscoped
之类的,可以把这里修改为 public
。默认是另外一个值,可以在官方 github
中查看。
预发布
pnpm changeset pre enter <tag> alpha | beta | rc |
退出预发布
pnpm changeset pre exit |
正式发布
pnpm changest && pnpm changest version && pnpm changest publish |
配置 changeset 发布流命令,在根目录的 package.json
添加以下命令:
"changeset": "changeset", |
其中: - changeset:生成临时的 changelog - update:version:消耗 changelog 生成组件的更新记录,并更新组件 version - release:发布组件
构建产物后发版本
{ |
栗子: // package.json 新增 如下配置
|
业务项目发布流是怎么样的?
- 不同开发者先开发,在提交 PR 时使用
pnpm changeset
写入一份变更集。 - 定期项目
owner
发包,使用pnpm vp
消耗所有变更集,由changesets
自动提升子包版本、生成changelog
。 - 执行
pnpm release
构建全部项目并发包。