如何管理pnpm monorepo多仓库模式下的版本与发包和给开源仓库提PR
作者:易师傅、github
声明:文章为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
前言大家好,我是易师傅,一个专门搞前端的搬(touch)砖(fish)师傅 ~
在上篇文章中《如何去搞 Vue/React Hooks 和 Utils 企业级开源工具库》中主要给大家介绍了如何从 0 到 1 搭建一个工具库;
正所谓,打铁要趁热 ~
这不,为了让各位大佬们都有参与感,同时也为了让大家了解熟悉开源项目的大致流程;
于是一个 A Crazy 开源工具库 vemjs 就此诞生了;
当然如果您对开源感兴趣,欢迎您加入我们的大家庭(已有五十多位大佬) ~
集思广益,因为身为万千优秀的贡献者的您,您的灵感是我们必不可少的一部分 ~
一、利用 changeset 规范 PR通过vmejs仓库,我们得知我们使用的pnpm workspace做的多仓库管理;
同时我们为了版本控制与pnpm monorepo更好的搭配,所以我们使用changeset来进行快速集成;
1. 安装changesetpnpmi@changesets/cli-Dw
2. 初始化changesetspnpmchangesetinit
就会生成一个.changeset/conifg.json文件,相关配置如下
{
"$schema":"https://unpkg.com/@changesets/config@2.2.0/schema.json",
"changelog":"@changesets/cli/changelog",//更新日志生成函数的加载地址
"commit":true,//自动提交version的改动
"fixed":[],//捆绑发布的包
"linked":[],//配置哪些包要共享版本
"access":"public",//公开,如果你想阻止一个包被发布到npm,在包的package.json中设置private:true(可选值:restricted,不公开)
"baseBranch":"main",//主分支名
"updateInternalDependencies":"patch",//是否主动更新package的依赖,patch、minor
"ignore":[]//指定不发布的包
}
3. 配置package.json的脚本"scripts":{
"change":"changesetadd",
"change:version":"changesetversion",
"release":"pnpmbuildpnpmrelease:only",
"release:only":"changesetpublish"
}
4 运行pnpm change主要目的就是生成changeset文件(就是下图中的 md 文件);
如下图所示,其中每个 md 文档就代表了你执行的pnpm changeset后生成的;
image.png需要注意的是执行pnpm change命令(上面changeset add 中的 add 可省略),会弹出一些询问窗口,主要分为三步:
哪些包是需要生成changeset文件的?此次发布包的版本是什么?(遵循 semver 规范);输入此次变更的描述信息以便生成到changeset文件中;5. 运行pnpm change:version主要目的就是消耗pnpm change生成的changeset文件,同时根据changeset文件中的内容生成对应子包的CHANGELOG信息;
image.png到这里你的生成changelog就已经完成,但是如果你想让你的 log 信息更详细一点,可以引入@changesets/changelog-github
6. 配置@changesets/changelog-github丰富生成的CHANGELOG.md(建议开源中引入,企业中不需)
1. 安装
pnpmi@changesets/changelog-github-Dw
2. 修改.changeset/conifg.json配置文件
{
...
"changelog":["@changesets/changelog-github",{"repo":"vmejs/vmejs"}],
...
}
3. 配置GITHUB_TOKEN
image.png4. 手动生成对应的消息需要配置环境变量(本地配置测试):
#win
setGITHUB_TOKEN=YourYoken
#mac
exportGITHUB_TOKEN=YourYoken
如果你不想配置,可以直接运行以下命令:
GITHUB_TOKEN=xxxpnpmchangesetversion
注意:因为是本地环境配置测试,所以后续自动化发布会自动鉴权是不需要在本地设置的
5. 再重复上面的执行pnpm change和pnpm change:version,会多了许多信息
image.png7. 运行pnpm release的最终发布image.png二、用 GitHub Action 做 CI/CD 流程1. 添加发布脚本编写对应的.github/workflows/release.yml执行脚本
#https://docs.github.com/en/actions/using-workflows/about-workflows
#整个工作流的名称
name:Release
#监听main分支的push事件(有更新时)
on:
push:
branches:
-main
#所有的jobs
jobs:
#定义一个名为release的job
release:
#指定运行所需要的虚拟机环境(必填)
runs-on:ubuntu-latest
#定义步骤
steps:
#https://github.com/actions/checkout
#拉取代码
-name:CheckoutRepo
uses:actions/checkout@v2
#https://github.com/actions/setup-node
#安装node
-name:SetupNode.js
uses:actions/setup-node@v3
with:
node-version:16.x
#https://github.com/pnpm/action-setup
#安装pnpm
-name:SetupPnpm
uses:pnpm/action-setup@v2
with:
version:7.x
#https://pnpm.io/zh/cli/install#--frozen-lockfile
#如果缓存没有命中,安装依赖
-name:Installdependencies
run:pnpminstall--no-frozen-lockfile--ignore-scripts
#https://github.com/changesets/action
#自动创建发布PR和发布npm
-name:CreateReleasePullRequestorPublishtonpm
uses:changesets/action@v1
#参数配置
with:
publish:pnpmrelease
version:pnpmchange:version
commit:'chore:versionpackages'
env:
NPM_TOKEN:${{secrets.NPM_TOKEN}}
GITHUB_TOKEN:${{secrets.GITHUB_TOKEN}}
因为其中逻辑错综复杂;
所以其中具体详细逻辑不做细述,大家只需明白这是一个自动化合并 PR和发布 npm的脚本即可;
2. 添加文档打包脚本编写对应的.github/workflows/docs-deploy.yml执行脚本
name:docs-deploy
on:#触发条件
#每当push到main分支时触发部署
push:
branches:[main]
jobs:
docs:
runs-on:ubuntu-latest#指定运行所需要的虚拟机环境(必填)
steps:
-uses:actions/checkout@v2
with:
#“最近更新时间”等git日志相关信息,需要拉取全部提交记录
fetch-depth:0
-name:Installpnpm
uses:pnpm/action-setup@v2
with:
version:7
-name:SetupNode.js
uses:actions/setup-node@v2
with:
#选择要使用的node版本
node-version:'16'
cache:'pnpm'
#如果缓存没有命中,安装依赖
-name:Installdependencies
run:pnpminstall--no-frozen-lockfile--ignore-scripts
#运行构建脚本
-name:Buildvitepresssite
run:pnpmdocs:build
env:
DOC_ENV:preview
NODE_OPTIONS:--max-old-space-size=4096
#查看workflow的文档来获取更多信息
#@seehttps://github.com/crazy-max/ghaction-github-pages
-name:DeploytoGitHubPages
uses:crazy-max/ghaction-github-pages@v2
#环境变量
env:
GITHUB_TOKEN:${{secrets.ACTION_SECRET}}
with:
#部署到gh-pages分支
target_branch:gh-pages
#部署目录为vitepress的默认输出目录
build_dir:packages/.vitepress/dist
三、贡献指南(提 PR)Node.JS = 16PNPM v71. 本地环境安装试运行```
# https
git clone https://github.com/vmejs/vmejs.git
# ssh
git clone git@github.com:vmejs/vmejs.git
# 进入 vmejs 目录
cd vemjs && pnpm install
```
2. 贡献流程先查阅文档是否有你所需要的函数方法;如果没有你想要的函数方法,你有两种方式:发起一个issues讨论,评审人评论PR Welcome表示该idea可行,然后你就可以 fork 代码开发了;关闭当前页面,骂一顿这个作者:这是什么 laji 库;3. 功能开发流程请先 fork 一份到自己的项目下,然后新建一个分支用于变更
image.png基于 fork 后的项目新建分支,新建功能分支(例如 feature-getDevice)
#https
gitclone你的fork项目https地址
#ssh
gitclone你的fork项目ssh地址
#进入vmejs目录
cdvemjspnpminstall
#新建功能分支
gitcheckout-bfeature-getDevice
完成对应函数方法(例如:https://github.com/vmejs/vmejs/blob/main/packages/core/getDevice/index.ts)
完成对应的测试用例(例如:https://github.com/vmejs/vmejs/blob/main/packages/core/getDevice/index.test.ts)
完成对应的使用文档(例如:https://github.com/vmejs/vmejs/blob/main/docs/packages/core/getDevice/index.md)
你可以本地执行一些命令:
"scripts":{
//本地打包
"dev":"tsup--watch",
"build":"tsup",
//本地打包文档
"docs:dev":"pnpm-Cdocsdev",
"docs:build":"pnpmrun-Cdocsbuild",
//本地执行eslintprettier检查
"lint":"eslint.--ext.vue,.js,.ts,.jsx,.tsx,.json--max-warnings0--cache",
"lint:fix":"pnpmrunlint--fix",
"format":"prettier--write--cache.",
//执行测试用例
"test":"vitesttest",
//测试用例覆盖率
"coverage":"vitestrun--coverage"
},
研发完成后需进行相关规则的 commit 检测
#1.检查代码格式
pnpmeslintpnpmformat
#2.执行测试用例
pnpmtest
#3.测试用例覆盖率
pnpmcoverage
以上全部 ok 后,一定要在本地执行pnpm change生成changeset文件
pnpmchange
Git上传:严格遵守 Git Commit 规范
typescope):subject
//注意冒号:后有空格
//如feat(user):增加用户中心的xx功能
复制代码
feat:新功能 featurebug:测试反馈 bug 列表中的 bug 号fix:修复 bugui:更新UI;docs:文档注释变更style:代码格式(不影响代码运行的变动);refactor:重构、优化(既不增加新功能,也不是修复bug);perf:性能优化;release:发布;deploy:部署;test:增加测试chore:构建过程或辅助工具的变动revert:回退build:打包scope表示 commit 的作用范围,如用户中心、购物车中心,也可以是目录名称,一般可以限定几种;
subject用于对 commit 进行简短的描述;
type必填,表示提交类型,值一般有以下几种:
统一格式:4. Code Review你 fork 的功能分支提交 PR 合并至main分支代码审核与优化审核人Approved后合入main分支四、目录结构项目采用Monorepo进行代码管理,下面展示了主要目录结构
root
├──docs#文档
│├──guide#指引文档
││└──index.md
│└──packages
│└──core#函数展示文档
│└──getDevice
└──index.md#函数方法文档
├──packages
│├──core#主工具函数Utils集合
││├──getDevice
││├──getxxxx
││└──其它
│└──shared#主工具函数公用方法集合
│├──is#方法集合
│├──xx
│└──其它#其它
└──playground#本地开发调试操场
工具函数目录结构 (以getDevice为例):
#packages/core/getDevice
core
└──getDevice
├──index.test.ts#单元测试
└──index.ts#函数方法入口
五、开源的意义这里借用阴明的一句话:开源即责任
一个好的软件项目是为了服务好用户,选择开源模式,本身就是选择了一个为解决复杂问题提供通用(高市占率)解决方案的途径;
选择开源模式,即提高了普及项目的速度,也就提高了你的软件被更多人依赖的可能;
开源更多的无非是时间与精力上的损耗,但是一旦你的软件被更多人认可,那即变成了对你的一种束缚,亦可称之为责任;
这也就是为什么,开源即责任。
开源的目的:
开源是为了更好地协作开发出解决用户需求的软件;开源是为了解决技术和架构的停滞不前而有的新思维;开源是为了从万千优秀的贡献者中汲取灵感,加速整个行业的创新;开源不仅是为自由软件做市场营销,更多应该是造福整个社区;总结如果您对开源感兴趣,欢迎您加入我们 ~
如果您对工具库感兴趣,欢迎加入我们 ~
如果您对Vue Hooks感兴趣,想写自己的 Hooks,欢迎加入我们 ~
如果您对React Hooks感兴趣,想写自己的 Hooks,欢迎加入我们 ~
如果您有更好的工具库 Idea,欢迎加入我们 ~
集思广益,因为身为万千优秀的贡献者的您,您的灵感是我们必不可少的一部分;
一个完善的工具库离不开万千函数的支撑、也离不开广大掘友们的支持;
您还在等什么,赶紧加入我们吧!联系 vx:JeddyGong
写得好了,您的点赞关注是我最大的鼓励 ??????
写的差了,您的评论批评是我最大的动力 ??????
只是其中有许多是需要我们优化的,这篇文章就不做详细的介绍了,因为每个优化都是一副长篇概论;
当然,既然做我们就要做好了,所以下面有几个自动化的优化是需要持续跟进的:
文档自动化打包,不需手动添加对应的路径;文档抽离成一个单独的 docs 目录(可忽略);changeset 的更多功能使用,让开源更加轻松;[已完成]~~Github 自动部署发布配置,自动 Tag/release 等[已完成]~~;开源贡献指导文档;[已完成]更多 cli 脚本;工具库模板地址:链接
Github 开源地址:链接
最后其实大家都明白做开源是一个很费劲的事,先不说出发点在哪;
究竟是单纯的开源,还是另有目的我想每个人的想法都不一样;
笔者的开源很简单,就是简简单单的爱好罢了,无欲无求就是最真实的写照;
该系列会是一个持续更新系列,关于前端基建,笔者主要会从如下图几个方面讲解,如果您想第一时间看到我的更新文章,可以关注我和我的《前端要搞基建》专栏
前端基建之路.png如果你对 Vite 感兴趣,可以看看我的专栏:《Vite 从入门到精通》
如果你对微前端感兴趣,可以看看我的专栏:《微前端从入门到精通》
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线