• 作者:老汪软件技巧
  • 发表时间:2024-09-12 04:01
  • 浏览量:

我对 monorepo 的一些思考前言

最近在自己的新项目中,使用了 monorepo-template 模板,并不断地做了不少改进。

在此,我想借此机会分享一下这个模板的演变过程,以及我对 monorepo 的一些思考。

它的由来

为了应对越来越多的发包场景,我创建了 npm-lib-template 模板

这是一个 git 单仓单 npm 包模板,使用 rollup 进行打包,然后再发布到 npm 和 github

然而,在后续开发中,我发现单仓库的模式在某些场景下难以应对。

例如,当需要引用其他自己的包,进行单元测试并再次发包时,这时候往往要在多个项目之间进行来回的切换更改,管理复杂度会迅速上升。

git submodule 也是另外一条路子,但是我对每次都要同步 hash 感到深恶痛绝,遂放弃 (不过某些极其特殊场景的实现,还是只能利用这个功能)。

因此,我决定要创建一个 monorepo 项目模板 ,以应对这些需求。

技术选型管理工具

在 monorepo 的管理上,我选择了 pnpm 和 turborepo 这对组合,原因很简单:它们都非常快。

语言与打包

我选择使用纯 TypeScript 来编写所有类库项目,并使用 tsup / unbuild 进行打包,默认输出格式为 cjs 和 esm,并利用 package.json 中的 exports 字段进行分发。

调试工具

在直接调试时,我抛弃了 dist + sourcemap 的调试方式,使用了 tsx,它非常适合调试 TypeScript 编写的 CLI 项目。

测试框架

测试方面,我选择了 vitest。

它不仅速度快,还很好地支持 cjs、esm 和 TypeScript,同时也适合 monorepo 项目。你可以利用 turbo 来执行单个的 vitest 任务,也可以利用 vitest.workspace 来进行多任务测试。

最初我使用的是 jest + ts-jest,但它对多格式的混合模块的支持不够理想,最终我选择了 vitest。

代码规范与质量控制

为了保持代码质量,我使用了 eslint 和 stylelint,并基于自己的配置包 @icebreakers/eslint-config 和 @icebreakers/stylelint-config 来进行代码格式化和规范化。

我还为 .vscode 配置了一些推荐插件和编辑器选项。

此外,通过 husky 添加了 git hook,配合 lint-staged 对提交的代码进行校验。与 commitlint 结合使用,以确保 git 提交信息符合规范。

本地引用与发包替换

利用 publishConfig 会在发包的时候替换 package.json 字段的方式,在本地包相互引用的时候,都使用 Typescript 源文件的方式导出,在 publishConfig 里定义的导出为,真正在不同环境中,指向 dist 中不同格式的产物地址。

通过这种方式,可以大大加速整个 monorepo 的开发测试速度,避免反复通过 watch 来构建 dist 和 sourcemap,也避免一构建出产物,对应的 Typescript 文件,就报错的问题。

发包流程

我采用了 changesets,它在 monorepo 环境下发布非常方便。功能非常的多,具体可以查看官方文档。

Github 相关配置

在 .github 目录下,我提供了默认的 CI/CD 流程配置,以及用户提交 issue 时的模板。经过少量配置后,就可以实现自动发布 npm 包、创建 git tag 以及生成 GitHub release。

此外,模板里还有许多为 GitHub 显示优化的 md 文档。

部署

文档网站通过 netlify.toml 配置部署在 Netlify 上。最初我使用的是 Vercel,但由于国内访问速度的原因,最终迁移到了 Netlify。

使用手册功能特性总结如何使用?

首先,访问本模板的 Github 地址,然后按照一下条件:

然后在根目录 (pnpm-workspace.yaml 所在的位置) 执行 pnpm i 去安装依赖

没有 pnpm 的,可以使用 npm i -g pnpm 来进行安装。

什么! 你不会连 nodejs 还没安装吧?

_思考的英文_思考图片

清除默认的包(可选)

执行 pnpm script:clean 命令,可以删去大部分的初始 repo,只保留一个 @icebreakers/bar 项目作为发包打包模板。

执行完成之后再去执行 pnpm i 来更新 pnpm-lock.yaml, 并提交来锁定版本

模板包介绍

默认把 repo 放在 packages 和 apps 这 2 个目录里面

packages

其中 tsup 是使用 esbuild 打包库的,unbuild 是使用老版本的 rollup 进行打包的

本来笔者是使用 rollup 来进行打包的 (weapp-tailwindcss 就是 rollup 打出来的) ,但是不够傻瓜无脑,所以用了 tsup

apps更新包的依赖

在根目录中执行 pnpm up -rLi 来进行包的交互式更新,下面是解释:

配置自动发包

本项目使用 changesets 进行包的发布和 changelog 的生成

在使用的时候,首先你需要做一些配置:

首先你需要安装 Github App: changeset-bot

然后,来到你复制这个模板仓库(repo), 上方里的 Settings Tab 页面,进行 2 个操作:

1. 在 Github 进行 PR 和发包

选择 Code and automation > Actions > General

然后在右侧 Workflow permissions 下方选择: Read and write permissions

然后选中 Allow GitHub Actions to create and approve pull requests

然后保存即可。

这样 changeset 就有权限对你进行 PR 和代码版本更新了!

2. 在 npm 发包

选择 Security > Secrets and variables > Actions

然后在右侧的 Repository secrets 设置你的 NPM_TOKEN 这个可以在你的 账号中生成获取

(假如你需要单元测试代码覆盖率,你需要设置 CODECOV_TOKEN)

内置脚本配置同步方式

在根目录下执行: npx @icebreakers/monorepo@latest

这个命令会把所有的文件从最新版本,对你本地进行覆盖,你可以从 git 暂存区把你不想要的文件剔除

参数

npx @icebreakers/monorepo@latest --raw

这个命令会从全部文件中去除 Github 相关的文件

npx @icebreakers/monorepo@latest -i

这个命令会进行命令行选择模式,你可以在这里对想要复制的文件进行筛选

当然你可以同时使用这 2 个命令

npx @icebreakers/monorepo@latest -i --raw

总结

从单仓到 monorepo 的转变不仅仅是对工具的选择,更是对项目管理模式的优化。

通过采用合适的工具链,能够更高效地管理多包项目的同时,利用 CI/CD 确保代码的质量和发布的顺畅。

希望我的这些思考对你有所帮助,也欢迎大家提出各种建议和意见。

相关文档见: 反正我以后创建项目的模板就用它了。

假如你都看到这了,说明我们是有缘之人,给我 monorepo-template 点个 Star 呗嘿嘿。


上一条查看详情 +奔跑吧武士,Android休闲小游戏开发
下一条 查看详情 +没有了