我对 monorepo 的一些思考

bg

我对 monorepo 的一些思考

  • 我对 monorepo 的一些思考
    • 前言
    • 它的由来
    • 技术选型
      • 管理工具
      • 语言与打包
      • 调试工具
      • 测试框架
      • 代码规范与质量控制
      • 本地引用与发包替换
      • 发包流程
      • Github 相关配置
      • 部署
    • 使用手册
      • 功能特性总结
      • 如何使用?
      • 清除默认的包(可选)
      • 模板包介绍
        • packages
        • apps
      • 更新包的依赖
      • 配置自动发包
        • 1. 在 Github 进行 PR 和发包
        • 2. 在 npm 发包
      • 内置脚本
      • 配置同步方式
        • 参数
    • 总结

前言

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

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

它的由来

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

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

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

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

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

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

技术选型

管理工具

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

  • pnpm 又可以节省磁盘空间,又能够链接自特定的内容寻址存储库,是为快也
  • turborepo 有构建缓存,是为快也too.

语言与打包

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

调试工具

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

测试框架

测试方面,我选择了 vitest

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

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

代码规范与质量控制

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

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

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

本地引用与发包替换

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

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

发包流程

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

Github 相关配置

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

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

部署

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

使用手册

功能特性总结

  • 强大的 monorepo 管理 (pnpm + turborepo)
  • 单元测试 (vitest)
  • 包括 cli bin 全部都是 typescript
  • 代码规范与质量 (eslint + @icebreakers/eslint-config + @icebreakers/stylelint-config)
  • git 提交规范 (husky + commitlint + lint-staged)
  • pnpm 部署 Docker 模板
  • Github Action 自动发布 npm, github release 包 (changeset)
  • 配置文件同步升级 npx @icebreakers/monorepo@latest

如何使用?

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

  • Github 账号的,可以登录后,点击右上角的 Use this template 按钮

  • 没有 Github 账号的,可以点击 Code 按钮,把这个仓库的源码,或 clone 或下载到本地

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

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

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

清除默认的包(可选)

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

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

模板包介绍

默认把 repo 放在 packagesapps2 个目录里面

packages
  • @icebreakers/bar - tsup 打包的库模板
  • @icebreakers/foo - unbuild 打包的库模板(不推荐,unbuild 很久没有更新了)
  • @icebreakers/monorepo - 本仓库的更新配置服务,可直接使用 npx @icebreakers/monorepo 执行远端 cli 命令

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

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

apps
  • @icebreakers/cli - 使用 typescript 编写的 cli 模板
  • @icebreakers/website - 文档网站模板,也是 monorepo.icebreaker.top 的源代码

更新包的依赖

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

  • -r : recursive 递归选中所有 repo
  • -L : latest 更新到最新
  • -i : interactive 交互式

配置自动发包

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

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

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

  2. 然后,来到你复制这个模板仓库(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 这个可以在你的 npmjs.com 账号中生成获取

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

内置脚本

  • pnpm script:clean 删去大部分的初始repo,只保留一个 @icebreakers/bar 项目作为发包打包模板
  • pnpm script:init 初始化一些 package.json 里的字段
  • pnpm script:sync 使用 cnpm sync 功能,把本地所有的包,同步到 npmmirror 上,需要安装 cnpm

配置同步方式

在根目录下执行: 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.icebreaker.top 反正我以后创建项目的模板就用它了。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/424582.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPU池化为实现Robotaxi按下快进键

日前,甲子光年智库推出《2022中国Robotaxi行业研究报告:探寻规模化商业落地之路》。Robotaxi(无人驾驶出租车)是自动驾驶技术发展应用的终极目标之一,新基建下的智慧共享出行将链接贯穿未来数智化生活全场景。 该报告从…

七. 部署YOLOv8检测器-quantization-analysis

目录 前言0. 简述1. 案例运行2. 补充说明3. 量化分析4. 探讨总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习课程第七章—部署YOLOv8检测器,一起来学习…

C语言:链表

链表是一种常见的基础数据结构,它由一系列节点(Node)组成。每个节点包含两部分:数据域(存储数据)和指针域(存储下一个节点的地址)。链表的特点是元素在内存中不一定连续存储&#xf…

BUUCTF 之Basic 1(BUU LFI COURSE 1)

1、启动靶场,会生成一个URL地址,打开给的URL地址,会看到一个如下界面 可以看到是一个PHP文件,非常的简单,就几行代码,判断一下是否有一个GET的参数,并且是file名字,如果是并且加载&a…

GEE:连续变化检测与分类(Continuous Change Detection and Classification, CCDC)教程

连续变化检测与分类(Continuous Change Detection and Classification, CCDC)是一种土地变化监测算法,旨在对卫星数据的时间序列进行操作,特别是Landsat数据。CCDC包括两个部分,其一是变化检测算法(Change …

python小脚本,实时监测服务器是否宕机状态,并发送到指定群组

一,前言 众所周知,市面上监控软件很多,有Zabbix,Prometheus等,但对于相对简单的功能,需要第一时间发现问题,如服务器宕机,zabbix和Prometheus都需要等几分钟才会报警。 想到最原始…

故障排查:VMware虚拟机网络冲突,导致VPN网络无法正常访问

故障现象 某台windows10系统电脑,远程拨号SSL VPN后,无法正常公司内网。通过排查,发现重启开机,操作系统的默认路由多了一条公司内网的默认路由,但网关不正确。手动删除,重启系统又恢复原样。 排查过程 c…

adb的安装和使用 以及安装Frida 16.0.10+雷电模拟器

.NET兼职社区 .NET兼职社区 .NET兼职社区 1.下载adb Windows版本:https://dl.google.com/android/repository/platform-tools-latest-windows.zip 2.配置adb环境变量 按键windowsr打开运行,输入sysdm.cpl,回车。 高级》环境变量》系统变量》…

OpenCV结构分析与形状描述符(20)计算一个包围给定点集的最小外接圆函数minEnclosingCircle()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 找到一个包围二维点集的最小面积的圆。 该函数使用迭代算法来寻找一个二维点集的最小外接圆。这意味着函数将会通过反复逼近的过程来计算出能够…

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测 目录 多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-LSSVM贝叶斯优化最小二乘支…

莎朗斯通的比基尼视频曝光了她的日常锻炼!自爆曾在重症监护室呆了9天

如果您错过了,莎朗斯通 (Sharon Stone) 的华丽比基尼视频向您展示了她的日常锻炼! 9 月 12 日,斯通分享了一段她在泳池里锻炼的视频。她分享了这段视频,并配文:“我刚刚和教练 kristinemarie_18 完成了最后一次锻炼&a…

【Python刷题】Atcoder Beginner Contest 371

目录 A - Jiro题目描述算法思路代码实现 B - Taro题目描述算法思路代码实现 D - 1D Country题目描述算法思路代码实现 E - I Hate Sigma Problem题目描述算法思路代码实现 A - Jiro 题目描述 有三个人,知道他们之中每两个人的年龄关系,输出年龄第二大的…

Unity实现自己的协程系统

为什么自己实现一套协程系统 协程(Coroutine)是一个强大且灵活的工具,它可以帮助开发者处理异步任务,例如等待某些事件、处理逐帧更新等。在Unity中,协程通常通过IEnumerator来实现,这种机制允许代码在执行…

效率神器来了:AI工具手把手教你快速提升工作效能

随着科技的进步,AI工具已经成为提升工作效率的关键手段。本文将介绍一些实用的AI工具和方法,帮助你自动化繁琐的重复性任务、优化数据管理、促进团队协作与沟通,并提升决策质量。 背景:OOP AI-免费问答学习交流-GPT 自动化重复性任…

IP纯净度对跨境电商有哪些影响

在全球化贸易的浪潮中,跨境电商凭借其打破地理界限的能力,成为推动国际贸易的重要力量。然而,跨境电商的运营并非没有挑战,其中IP纯净度是影响其成功的关键因素之一。本文将探讨IP纯净度对跨境电商运营的多方面影响,并…

从单体到微服务:FastAPI ‘挂载’子应用程序的转变

在现代 Web 应用开发中,模块化架构是一种常见的设计模式,它有助于将大型应用程序分解为更小、更易于管理的部分。FastAPI,作为一个高性能的 Python Web 框架,提供了强大的支持来实现这种模块化设计。通过“挂载”子应用程序&#…

WebGL系列教程八(GLSL着色器基础语法)

目录 1 前言2 基本原则3 基本数据类型4 顶点着色器和片元着色器4.1 声明4.2 初始化项目4.3 赋值 5 结构体5.1 声明5.2 赋值 6 函数6.1 基本结构6.2 自定义函数6.3 常用内置函数 7 精度8 其他9 总结 1 前言 通过前七讲,我们已经见过了WebGL中的部分基础语法&#xff…

webpack5-手撸RemoveConsolePlugin插件

写在前面 其实呢,这个东西也就那样,主要是我们得清楚webpack构建过程中的生命周期钩子, 就拿这个插件来说,我们想要把输出的js文件里面的内容中的console语句去掉,那么我们就需要找到webpack处理完文件时的钩子&#…

海外VS国内:网安上市公司人均创收对比

二级市场分析章节中分析了中国网络网络安全上市公司人均创收63.2万、人均毛利37.6万,人均创利-1.6万。 有网友问了:海外网络安全公司的人均情况如何?那么让我们一起看看吧。 我们统计了在海外上市的28家主要网络安全公司的2023年的人均情况&…

2020ICPC上海 D - Walker M - Gitignore

D: 首先显然要二分,判断当前二分的mid时间下是否能满足走满0~n 枚举所有情况,这里按照左,右起点p1,p2分别讨论 p1向左 p2向左(以下向左和向右都代表向左或者向右到墙,而不代表初速度方向),只需要计算p1或者p2反弹之后还能走距离n就是合法 p1向左 p2向右&#xff…