当前位置: 首页 > news >正文

我对 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 呗嘿嘿。

相关文章:

我对 monorepo 的一些思考

我对 monorepo 的一些思考 我对 monorepo 的一些思考 前言它的由来技术选型 管理工具语言与打包调试工具测试框架代码规范与质量控制本地引用与发包替换发包流程Github 相关配置部署 使用手册 功能特性总结如何使用?清除默认的包(可选)模板包介绍 packagesapps 更新…...

Java学习Day41:骑龙救!(springMVC)

springMVC与sevlet都是对应表现层web的,但是越复杂的项目使用SpringMVC越方便 基于Java实现MVC模型的轻量级web框架 目标: 小案例: 1.导入依赖 spring-context: 提供 Spring 框架的核心功能,如依赖注入、事件发布和其他应用上…...

Redis 常用命令总结

文章目录 目录 文章目录 1 . 前置内容 1.1 基本全局命令 KEYS EXISTS ​编辑 DEL EXPIRE TTL TYPE 1.2 数据结构和内部编码 2. String类型 SET GET MGET MSET SETNX INCR INCRBY DECR DECYBY INCRBYFLOAT 命令小结 内部编码 3 . Hash 哈希类型 HSET …...

Mysql SqlServer 分页

一、MySQL分页 SELECT column1, column2 FROM table ORDER BY column1 LIMIT Offset, Fetch; SELECT column1, column2 FROM table WHERE id BETWEEN StartId AND EndId ORDER BY column1; 二、Sql Server 分页 SELECT column1, column2 FROM table ORDER BY column1 OFFSE…...

电子支付原理

电子支付原理 1.电子支付概述2.线下支付概念和一般流程线下支付技术分类 3.线上支付概念和一般流程 参考自:https://www.topsec.com.cn/uploads/2023-10-08/49dab9d0-004b-4955-808a-d1c83998b8191696745486491.pdf 1.电子支付概述 电子支付通用支付流程一般涉及四…...

什么是OAuth 2.0?OAuth 2.0的工作流程是什么?与OAuth 1.0有哪些区别?

在浏览网页时,你肯定会遇到允许你使用社交媒体账户登录的网站。此功能一般是使用流行的OAuth 2.0框架构建的。OAuth 2.0是对OAuth 1.0的彻底重写,OAuth 2.0与OAuth 1.0或1.1不向后兼容。 1. OAuth产生背景 为了更好的理解OAuth,我们假设有如…...

Unity+LeapMotion2的使用

开始吧 导入步骤1.到官网下载软件并安装2.安装插件3.场景中添加检测管理器4.场景中添加手部模型 更多细节 导入步骤 1.到官网下载软件并安装 地址 重启电脑后连接设备 可以看到连接成功 2.安装插件 (也可以看官方教程) Project—>PackageManag…...

【CanMV K230 AI视觉】 跌倒检测

【CanMV K230 AI视觉】 跌倒检测 跌倒检测 动态测试效果可以去下面网站自己看。 B站视频链接:已做成合集 抖音链接:已做成合集 跌倒检测 跌倒检测主要根据人体姿态来判断,可以用于老人、小孩跌倒监护。 实验名称:跌倒检测 实验…...

谈谈PCIe VID、DID、SSID、SSVID背后的智慧

PCIe Vendor ID 想了半天还是觉得从“ID是什么”这个问题开始比较好。那么ID是什么?ID就是身份。那身份又是什么?身份就是一个合理存在,用于区分不同个体。为什么叫“合理存在”呢?如果国家不给你发身份证,你就是黑户…...

9月11日

使用绘制事件完成钟表的绘制 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTcpSocket> #include<QMessageBox>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpub…...

昇腾310内存拷贝测试

目的 从服务器将数据拷贝到昇腾310 ai卡 结论 数据进入到服务器后的内存不能直接用昇腾acl接口拷贝到AI卡。 需要 1&#xff09;先用acl接口申请内存&#xff1b; 2&#xff09; 将数据拷贝到acl申请的内存 3&#xff09;用acl接口将数据拷贝到AI卡 makefile # Copyri…...

‘$store‘ is not defined.

vueX不知道是否发挥作用&#xff1f;this.$store获取不到store/index.js中的数据 原因&#xff1a;版本问题 vuex版本不对&#xff0c;获取不到store 默认版本说明vuevue3vueXvue4vuex4只能在vue3中使用 vue默认vue3版本&#xff0c;vuex默认vuex4版本&#xff0c;vuex4只能…...

如何利用Linux提升工作效率和安全性?

Linux&#xff0c;作为一款自由和开放源代码的操作系统&#xff0c;已经在全球范围内得到了广泛的应用。无论是服务器、云计算、物联网&#xff0c;还是超级计算机&#xff0c;Linux都扮演着重要的角色。本文将深入探讨Linux的应用场景&#xff0c;以及如何利用Linux提升工作效…...

初始Linux 和 各种常见指令

目录 Linux背景 1. 发展史 Linux发展历史 1.历史 2. 开源 Linux下基本指令 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09;&#xff1a; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a; …...

【稀疏矩阵】使用torch.sparse模块

文章目录 稀疏矩阵的格式coocsrcsc Construction of Sparse COO tensorsConstruction of CSR tensorsLinear Algebra operations&#xff08;稀疏与稠密之间混合运算&#xff09;Tensor methods and sparse&#xff08;与稀疏有关的tensor成员函数&#xff09;coo张量可用的ten…...

如何增加谷歌网站曝光率?

增加谷歌网站曝光率其实就是让更多的人在搜索相关内容时&#xff0c;能看到你的网站。首先你就要搞清楚用户在搜索什么&#xff0c;这样才能把正确的内容呈现在他们面前。首先&#xff0c;你得站在用户的角度思考&#xff0c;想想他们在搜索与你网站相关的信息时&#xff0c;可…...

虚幻中的c++(持续更新)

文章目录 虚幻中的cUPROPERTY参数 UFUNCTION参数 虚幻中的c UPROPERTY 是虚幻中用于声明属性的宏&#xff0c;它用于标记某个属性是一个虚幻托管的属性&#xff0c;并且可以在编辑器中进行访问和操作。其提供了一系列参数&#xff0c;用于定义属性的各种行为&#xff0c;例如是…...

83-MySQL 索引有几种

MySQL中的索引主要有以下几种&#xff1a; 普通索引&#xff1a;最基本的索引类型&#xff0c;没有唯一性的限制&#xff0c;可以通过多个字段创建复合索引。 唯一索引&#xff1a;与普通索引类似&#xff0c;但区别在于唯一索引的每一个索引值只对应唯一的数据记录。 主键索…...

文献解读-The trans-omics landscape of COVID-19

关键词&#xff1a;流行病学&#xff1b;基因测序&#xff1b;变异检测&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;The trans-omics landscape of COVID-19 标题&#xff08;中文&#xff09;&#xff1a;COVID-19的跨组学全景 发表期刊&#xff1a…...

Unity核心实践小项目

要源码包的私信我。 简介 衔接Unity核心学习后的实操小项目 需求分析 准备工作 面板基类 为了能够控制一画布整体的透明度&#xff0c;所以需要给每个面板都添加一个 CanvasGroup组件 UI管理器 UGUI方面的参数设置 开始场景 场景搭建 直接用资源包搭建好的场景&#xff1a;…...

Avaloia 实现国产麒麟系统中文显示界面

最近在搞一个国产麒麟系统的接口对接&#xff0c;因为&#xff0c;接口内含复杂的签名验证&#xff0c;而且还是离线环境&#xff0c;所以&#xff0c;postman不是很好用。 就想着哪个方式好一些&#xff0c;主要是有选择图片的操作&#xff0c;所以&#xff0c;在Electron和A…...

pytest 生成allure测试报告

allure的安装 github地址 allure资产列表 windows下载.zip&#xff0c;解压并配置环境变量PATH&#xff1b;linux下载tar.gz&#xff0c;解压配置&#xff1b; allure作为pytest插件 # 安装 pip install allure-pytest# 执行单元测试&#xff0c;生成allure测试数据&…...

查询GPU版本以及PyTorch中使用单GPU和多GPU

文章目录 多GPU介绍GPU可用性及版本检查使用单个GPU使用多个GPU多GPU介绍 多GPU是指使用多个显卡来同时进行计算,以加速深度学习模型的训练和推断。每个GPU都有自己的内存和计算能力,通过同时利用多个GPU可以并行地执行模型的计算,从而提高整体的计算效率。 GPU可用性及版…...

基于SpringBoot+Vue的线上考试系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的线上考试…...

动手学深度学习(pytorch土堆)-02TensorBoard的使用

1.可视化 代码使用了 torch.utils.tensorboard 将数据记录到 TensorBoard 以便可视化。具体来说&#xff0c;它将标量数据记录到目录 logs 中&#xff0c;使用的是 SummaryWriter 类。 代码分解如下&#xff1a; SummaryWriter("logs")&#xff1a;初始化一个 Ten…...

STM3学习记录

一、串口 1.串口定义&#xff0c;将串口相关寄存器的首地址强制转化为串口结构体&#xff0c;方便通过结果体访问串口的寄存器 #define __IO volatile /*!< Defines read / write permissions */ typedef struct {__IO uint32_t SR; /*!< US…...

【网络】应用层协议-http协议

应用层协议-http协议 文章目录 1.Http协议1.1什么是http协议1.2认识URL1.3urlencode和urldecode1.4HTTP请求协议格式1.5HTTP响应协议格式1.6HTTP常见的Header1.7HTTP常见状态码1.8HTTP的方法1.8根据url调取对应的服务 2.cookie和session2.1cookie2.2session 3.HTTPS协议3.1对称…...

【python】OpenCV—Mask RCNN for Object Detection and Instance Segmentation

文章目录 1、任务描述2、MASR RCNN 网络结构3、方法实现4、结果展示5、涉及到的库getPerfProfile 6、参考 1、任务描述 利用 mask rcnn 网络&#xff0c;进行图片和视频的目标检测和实例分割 2、MASR RCNN 网络结构 3、方法实现 # Copyright (C) 2018-2019, BigVision LLC (L…...

通过 Python 使用 Pexels图片库 API 打造个性化壁纸应用

在数字时代&#xff0c;照片不仅仅是回忆的载体&#xff0c;它们还是我们生活的美丽装饰品。想象一下&#xff0c;如果你能轻松地将世界上最美的免费图片应用到你的应用程序中&#xff0c;岂不是让你的程序立刻闪亮起来&#xff1f;好消息是&#xff0c;这不仅仅是一个梦想。今…...

多线程篇(其它容器- CopyOnWriteArrayList)(持续更新迭代)

一、CopyOnWriteArrayList&#xff08;一&#xff09; 1. 简介 并发包中的并发List只有CopyOnWriteArrayList。 CopyOnWriteArrayList是一个线程安全的ArrayList&#xff0c;对其进行的修改操作都是在底层的一个复制的数 组&#xff08;快照&#xff09;上进行的&#xff0…...