我对 monorepo 的一些思考

news2024/9/25 17:17:09

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.coloradmin.cn/o/2126096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

25虾皮笔试shopee笔试测评sea笔试测评题型

虾皮笔试shopee笔试测评用的自己的笔试系统,全英文笔试: 1.Numerical Reasoning Test:10题,言语推断和数学计算 2. Verbal Reasoning Test:10题,言语理解,每题一段英文材料,选对错…

医院管理|基于java的医院管理系统小程序(源码+数据库+文档)

医院管理系统小程序 目录 基于java的医院管理系统小程序 一、前言 二、系统设计 三、系统功能设计 医生信息管理 排班信息管理 科室信息管理 科室预约 病历信息 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取:…

浅谈模型在信贷营销中的应用

浅谈模型在信贷营销中的应用 当前在信贷营销场景中,用户流量竞争愈加激烈,获客成本持续攀高,客户消费观念和消费信心趋向保守,传统的信贷营销方式效果逐渐乏力,借助数据挖掘技术对用户进行多元优化及精细化管理已经成为企业在经营发展中的普遍趋势。在此背景下,本文将围…

如何设置新建每个Python文件开头带上作者名和时间?

1、在pycharm界面中点击"File->Settings" 2、点击"Editor->File and Code Templates->Python Script" 3、添加信息后,点击"ok" # encoding: utf-8 # File : ${NAME}.py # Author: jianlu # Date : ${YEAR}/${MONTH}/${DA…

LBS 开发微课堂|轨迹重合率分析API升级:距离无上限,操作更简便

为了让广大的开发者 更深入地了解 百度地图开放平台的 技术能力 轻松掌握满满的 技术干货 更加简单地接入 位置服务 我们特别推出了 “位置服务(LBS)开发微课堂” 系列技术案例 第二期的主题是 《轨迹重合率分析API升级》 百度地图的鹰眼轨迹…

算法设计(一)

1.汉诺塔 介绍 汉诺塔(Hanoi Tower):它描述了如何将一堆大小不同、穿在一根柱子上的盘子移动到另一根柱子上,同时满足以下规则: 每次只能移动一个盘子。 每个移动盘子时,大的盘子不能放在小的盘子上面。 可以使用一根…

若依RuoYi项目环境搭建教程(RuoYi-Vue + RuoYi-Vue3版本)

文章目录 一、开发脚手架选择二、RuoYi框架1、介绍2、版本发展3、为什么选择若依4、优缺点5、项目内置功能 三、后端项目部署1、拉取源码2、环境要求3、Maven构建4、MySQL相关(1)导入SQL脚本(2)配置信息 5、Redis相关(…

crdownload格式后缀的文件是什么东西?crdownload格式是什么

crdownload格式就是浏览器没下载完成的文件,如果下载完成了,那么就显示正常的格式和文件名了。

ARM32开发——DMA

🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 基础概念CPURAM外设 ARM32程序存储 执行过程取数据 执行操作流程总结 基础概念 CPU CPU(Central Processing Unit&am…

[点云处理] cloud compare二次插件功能开发(三)CC插件总结与加速开发

本文完成一个点云变换的插件,同时也是对CC接口的使用做进一步说明,进一步理解CC插件开发流程,利用CC平台和已有代码加快实现定制功能。 这个功能在 cc 已有的功能已经存在,位于 edit->apply_transformation 这里 文件逻辑组织还…

如何让人工智能训练更快

影响人工智能训练时间的因素 在深度学习训练中,训练时间的计算涉及到多个因素,包括 epoch 数、全局 batch size、微 batch size、计算设备数量等。下面是一个基本的公式来说明这些参数之间的关系(注意,这只是一个基本的说明公式&…

改变事件

窗口的某些属性的状态发生改变时就会触发该事件 对应的事件类型包括 QEvent::ToolBarChange, QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,QEvent::StyleChange, QEvent::PaletteChange, QEvent::WindowTitleChange, QEvent::IconTextChange, QEve…

【大模型基础】P2 Bag-of-Words

目录 词袋模型 概述词袋模型 实例第1步 构建语料库第2步 对句子进行分词第3步 创建词汇表第4步 转换词袋表示第5步 计算余弦相似度 词袋模型的局限性 词袋模型 概述 词袋模型,Bag-of-Words,是一种简单的文本表示方法,也是 NLP 中的一个经典模…

【Arcgis基础教程】GIS数据制备,空间分析与高级建模实践应用

随着信息技术的发展,数字地球、智慧地球等新概念的出现,人们对信息的需求日益提高,使得地理信息系统(GIS)在国民经济各个行业中获得了日益广泛的应用。尤其在当今大数据时代,面对海量的空间数据及个性化的地理信息服务,如何高效地…

Outlook如何归档?

文章目录 一. 目的二. 问题详述三. 解决办法1、打开ouutlook文件2、设置存档文件夹3、设置存档文件夹4、选中邮箱点击确定5、如果备份失败的操作方法 四. 注意事项 一. 目的 解决OUTLOOK邮箱爆满造成无法接收邮件的问题…

猫头虎分享:看完百度内部讲话,整理出李彦宏关于大模型的10个判断

🦁 猫头虎分享:看完百度内部讲话,整理出李彦宏关于大模型的10个判断 📢 大家好!我是猫头虎技术团队的首席写作官。今天为大家带来一篇重量级内容:从百度内部讲话中,整理了李彦宏对大模型的10大…

LIO-SAM如何保存地图

一、找到LIO-SAM配置文件,路径为config/params.yaml,修改以下两项参数: savePCD: true # https://github.com/TixiaoShan/LIO-SAM/issues/3savePCDDirectory: "/home/slam/catkin_ws/src/maps" …

通讯录 - 动态内存开辟版本

文章目录 前言 一、思想 二、contact.h 三、test.c 四、contact.c 1、初始化通讯录 2、判断容量 3、增加联系人 4、封装的查找的函数 5、删除联系人 6、查找联系人 7、修改联系人 八、展示通讯录 九、排序 十、释放空间 总结 前言 路漫漫其修远兮,吾将上下而求索&…

盘点2024年4款高质量的英语翻译工具

英语目前对我们来说仍然是一门很重要的语言,在日常生活中,如果我们需要频繁的接触到英语的话,除了要积极提升自己的英语翻译能力之外,借助一些高效的英语翻译工具也是很有必要的。所以今天就跟大家分享一些我觉得比较好用的翻译工…

Kotlin 特性之扩展函数

什么是扩展函数 扩展函数是 Java 不具备的,而 Kotlin 独有的特性,在日常开发中使用频率很高,类似于设计模式中的装饰模式,其作用就是在不改变原有类的情况下,扩展新的功能。 如何使用扩展函数和扩展属性 扩展函数的…