从 Lerna 到现代化:原生 Workspaces 和 Changesets 的高效协作

在这里插入图片描述


1. 背景

最近新接手的一些 monorepo 的库项目,项目是用 lerna 进行管理的,使用过程中有一些不丝滑的地方,包括:

  1. lerna 版本过旧,使用 4.0.0(现版本 8.1.3),功能差异过大,很多功能特性被新版本移除。
  2. 发库版本过于繁琐和麻烦,对 git 侵入性很强。如果对 lerna 工具链不熟悉,很难操控。
  3. lerna 太强大,也带来来巨量的配置参数,数了一下,共有 15 个命令,134 的 cli 入参。

通过 lerna 官网可以看到,它诞生背景解决的包管理的问题,现在的包管理工具,如 npm、pnpm、yarn 等都已经支持,官方也呼吁有此功能需求的,建议不要再用 lerna 了,因为这些功能 lerna 已经全部移除。

原文:
Lerna is the original monorepo/workspace tool in the JavaScript ecosystem. When it was created in 2015/2016 the ecosystem looked totally different, and there were no built in capabilities to handle working with multiple packages in a single repository (a “workspace”). Commands like lerna bootstrap, lerna add and lerna link were all a critical part of the lerna project, because there were no other options.

However, the fact is that - for many years now - the package managers we know and love (npm, yarn and pnpm) all fully support that concept of workspaces as a first-class use-case.

They have battle tested implementations covering adding, removing and linking local packages, and combining them with third party dependencies in a natural way.

This is the reason why, for the final several years of his tenure as lead maintainer of lerna, Daniel, had been encouraging folks to strongly reconsider their use of the legacy package management commands in lerna, and instead leverage their package manager of choice to do what it does best.

We knew about this context from afar, but as new stewards of the project in 2022 we did not want to jump straight in and start removing capabilities without first taking the time to get familiar with the reality up close. Now that we have been actively maintaining for a while, we are in full agreement with Daniel and others that the legacy package management commands in lerna needed to be retired.

By removing these legacy pieces which have better alternatives natively in package managers, we and the rest of the lerna community are now freed up to concentrate our efforts on things which are uniquely valuable about lerna (such as, but not limited to, versioning and publishing), and making them the best they can be!

在此背景下,也有了对于 monorepo 的改造。
核心诉求是,操作更简单,使用更方便,保持技术先进性。

2. lerna 解决的问题

回到为什么使用 lerna,看下 lerna 到底解决了哪些问题。

早期的 lerna 主要解决:

  1. 支持链接 monorepo 中的不同项目,实现相互导入,而不用发布 npm 来消费。可以简单理解为 npm link
  2. 任意数量的项目,只需要运行一个命令。如根目录执行 lerna bootstrap就可以给所有包进行安装和链接。包括 lerna run --scope my-component test 等。
  3. 提供包的版本能力。
  4. 提供包的发布能力。

上面的 1 和 2,在 lerna 7就没了,官方文档中也不在提及。

3. 现代化替代方案

接下来看下,现在的替代方案。

3.1 原生 npm workspace 解决1、2问题

从 npm 7 https://docs.npmjs.com/cli/v7/using-npm/workspaces 开始(最新 10.8.1),就支持了 workspace 的能力。

packages/ 下的所有包,就可以在 package.json 下这样写:

{"workspaces": ["./packages/*"]
}

npm i 时,workspace 下的包都会进行安装。

通过 --workspace 参数,可以针对性执行命令,如 npm run test --workspace=a --workspace=b

但原生 npm 下做 dependencies 中的 workspace link 还是不好用。
下面看 pnpm。

3.1.1 pnpm 支持

pnpm 的优势非常多,在最直观的软、硬链安装方案来降低磁盘使用空间和提升安装速度外,对 workspace 的支持也是十分友好。

workspace 的作用范围在 pnpm-workspace.yaml 中进行声明,如:

packages:- 'packages/*'

pnpm i 时,workspace 下的包都会进行安装。

另外支持 workspace:协议,可以保证 workspace 内消费的包,都是 workspace 内的,这个非常方便。

同时在执行 pnpm publish 发包时,pnpm 会自动修改包的 package.json 中的,对于 workspace 的依赖版本为实际的版本。

在执行命令方面,支持 pnpm run 命令,它支持 --recursive,可以实现根据依赖顺序执行。比如 workspace 中,a 包依赖 b 包,则执行 pnpm run build --recursive进,会先为 b 包执行 build,然后再在 a 包执行 build。

同时支持 --filter参数,是的操作非常灵活。

3.2 版本及发布能力

在讲替换前,先看一下原来的执行流程,这里先看 lerna version

下面是 lerna version 最基本的执行流程:

这里面做了很多事情,对 git 强依赖,比如上面的流程就至少经历了下面的命令:

  • 本地是否有过提交:git rev-list --count --all --max-count=1
  • 取当前分支名:git rev-parse --abbrev-ref HEAD
  • 远端是否存在当前分支:git show-ref --verify refs/remotes/origin/<branch>
  • 当前分支是否落后于远程分支:git rev-list --left-right --count origin/<branch>...<branch>
  • 本地当前分支上一个 tag,及版本,及当前版本的 commit 数量,及本地是否有文件修改:git describe --always --long --dirty --first-paren
  • 判断相对 tag,当前是否有文件变化:git diff --name-only <tag>
  • git push --follow-tags --no-verify --atomic origin <branch>

所以要想让 lerna version 正常工作,你必须在此之前,完成以下工作:

  • 将你的本地 git branch 的 HEAD 与 remote 对齐
  • 本地 git branch 必须要在 remote 存在
  • 本的 git branch 的 commit 必须多于最近的一个 git tag 的数量

满足不了,你加上 --force-publish 参数都不会工作。

还有,当你没用 lerna 去打 tag,而是自己手动打了一个,会使 tag 缺少注视,修复起来也麻烦,需要执行:

GIT_AUTHOR_NAME="$(git show $1 --format=%aN -s)"
GIT_AUTHOR_EMAIL="$(git show $1 --format=%aE -s)"
GIT_AUTHOR_DATE="$(git show $1 --format=%aD -s)"
GIT_COMMITTER_NAME="$(git show $1 --format=%cN -s)"
GIT_COMMITTER_EMAIL="$(git show $1 --format=%cE -s)"
GIT_COMMITTER_DATE="$(git show $1 --format=%cD -s)"git tag -a -m $1 -f $1 $1git push --tags --force

重新订正。

这种强依赖 git 有好处也有坏处。就比如你先 git push 了,而没 lerna version,那再去打 version,苦不堪言。

3.2.1 拥抱 changesets

changesets 是完美替代 lerna 3、4(包版本、包发布)功能的工具,使用简单,符合直觉。最大的优点在于提供了很大的自主权在用户手中。‍⁢

changesets 基本和 git 没啥太大关系,除了打 tag 的功能。替代命令是 changeset versionchangeset publish

现在的 version 流程:

将 pre-release 的判断前置,然后增加 add 能力,自动记录影响范围和内容,最后通过 version 自动聚合 CHANGLOG.md,并为所有包生成合适的版本号。

最后 publish 直接与 npm server 交互,只有当版本已经在 npm server 上存在外,其它都可正常发布。

monorepo 比较核心的问题也是 lerna 的主要能力。但今天 workspace 的能力原生已经支持了,包版本处理和发布的能力,changesets 也已经解决了。


微信搜索“好朋友乐平”关注公众号。

github原文地址

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

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

相关文章

前端JS必用工具【js-tool-big-box】学习,检测密码强度

js-tool-big-box 前端工具库&#xff0c;实用的公共方法越来越多了&#xff0c;这一小节&#xff0c;我们带来的是检测密码强度。 我们在日常开发中&#xff0c;为了便于测试&#xff0c;自己总是想一个简单的密码&#xff0c;赶紧输入。但到了正式环境&#xff0c;我们都应该…

FullCalendar日历组件集成实战(8)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

【算法每日一练】新月轩就餐

思路&#xff1a; 其实很容易想到是双指针或者双端队列。 我们设置一个type表示当前区间已经有了多少种厨师&#xff0c;同时还需要记录区间中每个元素出现的次数&#xff0c;然后比较棘手的是移动问题了&#xff0c;什么时候移动呢&#xff1f; 我们可以发现当区间当队头元…

手眼标定学习笔记

目录 标定代码&#xff1a; 手眼标定原理学习 什么是手眼标定 手眼标定的目的 eye in hand eye to hand AXXB问题的求解 标定代码&#xff1a; GitHub - pumpkin-ws/HandEyeCalib 推荐博文&#xff1a; https://zhuanlan.zhihu.com/p/486592374 手眼标定原理学习 参…

国产操作系统上Vim的详解01--vim基础篇 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上Vim的详解01–vim基础篇 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产操作系统上使用Vim的详解文章。Vim是一款功能强大且高度可定制的文本编辑器&#xff0c;广泛应用于编程和日常文本编辑中。…

记一次cms代码审计

000&#xff1a;前言 记录一次小型cms代码审计 001&#xff1a;任意文件删除 由于代码繁杂&#xff0c;不再一一展示 /app/controller/kindeditor.class.php 关键漏洞代码 public function delete() {$path ROOT_PATH.$_GET[pic];unlink($path);$flash M("flash&qu…

Postgre数据库初探

一、PostgreSQL介绍 PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES&#xff0c; 版本 4.2为基础的对象关系型数据库管理系统&#xff08;ORDBMS&#xff09;。POSTGRES 领先的许多概念在很久以后才出现在一些商业数据库系统中。 PostgreSQL是最初的伯克利代码的开…

vscode编译c/c++找不到jni.h文件

解决办法: 一、下载JDK 访问Oracle官网的Java下载页面&#xff1a;Java Downloads | Oracle 选择适合您操作系统的JDK版本&#xff1a; 对于Windows&#xff0c;选择“Windows x64”或“Windows x86”&#xff08;取决于您的系统是64位还是32位&#xff09;。对于Linux&#…

RPM包方式离线部署gitlab

下载安装包 要求&#xff1a;可以联网&#xff0c;系统及版本与目标服务器一致。配置gitlab yum仓库 curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash 新建包存放目录 mkdir /root/gitlab 下载gitlab及相关安装包 …

老赛棍版端口,扫别人没扫到的资产

0x001 获取目标信息 因为某些敏感原因&#xff0c;这部分干脆以长沙为例&#xff0c;仅做查询方式参考。首先FOFA搜&#xff1a;region"Hunan" && city"Changsha"&#xff0c;全部转换为C段后去重&#xff0c;就得到该城市的大致网段&#xff1a;…

Android O Camera深度研究

目录 Adnroid O之前的Android camera软件框架 Adnroid O camera软件框架 Passthrough Mode Binderized mode Wrapper shim for libhardware HALs Wrapper shim for libhardware HALs Customized Treble Camera HAL/framework Camera HAL transition and removal plan …

Android精通值Fragment的使用 —— 不含底层逻辑(五)

1. Fragment 使用Fragment的目标&#xff1a;根据列表动态显示内容&#xff0c;更简洁显示界面、查找界面 eg. 使用新闻列表动态显示新闻 1.1 Fragment的特性 具备生命周期 —— 可以动态地移除一些Fragment必须委托在Activity中使用可以在Activity中进行复用 1.2 Fragmen…

新鲜速递:图解新颖LLM的CoPE位置编码

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提供了大模型领域最新技…

基于docker的oracle12.2.0.1部署及oracle使用与docker镜像容器制作迁移方法

基于docker的oracle12.2.0.1部署及oracle使用与docker镜像容器制作迁移方法 本文介绍了基于docker的oracle12.2.0.1部署&#xff0c;包含了oracle基本配置、监听器和实例启动方法、PDB和CDB操作方法、表空间建立和用户数据库建立、常见启动问题解决等&#xff0c;并介绍了镜像制…

二、go微服务项目“商城项目实战开发”第二步grpc和gin的直连调用

文章目录 商城项目实战开发-GRPC和GIN的直连调用01、本次课程微服务的技术栈02、用户服务接口定义和实现登录1、密码问题01、MD5的方式02、加盐的方式03、动态盐04、使用加盐框架passwordEncoder2、用户服务接口的暴露3、Grpc的实现步骤1.定义暴露接口2.编写user的调用文件3.编…

YOLOv8_obb预测流程-原理解析[旋转目标检测理论篇]

YOLOv8_obb的预测流程,主要分预处理模块、推理模块和后处理模块。这里面有很多内容是和目标检测预测流程是重合的,主要区别在于Angle分支、NMS后处理以及regularize_rboxes部分。本文也主要介绍一下这三个模块,其他模块可以结合YOLOv8预测流程-原理解析[目标检测理论篇]一起…

免费SSL证书的安全性与获取指南

SSL证书是一种数字凭证&#xff0c;用于加密用户与网站之间的信息交换&#xff0c;以确保传输的数据不被第三方窃取。它像是一个数字版的密封印章&#xff0c;为数据的传输过程提供了一层保护膜。 免费的SSL证书通常由CA机构提供&#xff0c;它们同样可以提供基础数据的加密服…

16.Redis之Redis事务

1.MySQL 事务 原子性: 把多个操作,打包成一个整体了 一致性: 事务执行之前,和之后,数据都不能离谱~ 持久性: 事务中做出的修改都会存硬盘 隔离性: 事务并发执行,涉及到的一些问题~~ 2.Redis事务 2.1 认识Redis事务 • 弱化的原⼦性: redis 没有 "回滚机制". …

.NET最新漏洞 | 某SLMS系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

翻译《The Old New Thing》- How do I force the ECHO command to echo?

How do I force the ECHO command to echo? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080403-00/?p22883 Raymond Chen 2008年04月03日 如何强制执行ECHO命令以进行回显&#xff1f; 简要 ECHO命令用于在命令行打印文本&#xff0…