问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

lerna+yarnworkspace使用总结

发布网友 发布时间:2024-10-02 03:41

我来回答

1个回答

热心网友 时间:2024-12-09 19:16

前言

本文是笔者在学习和应用lerna+yarnworkspace多包工程化管理模式的过程中,记录的一些使用和问题汇总,作为笔记和分享于大家阅读。

lerna管理方式属于Monorepo模式,这有别于传统的Multirepo单仓库应用模式,下面我们先来了解一下两者的区别。

模式对比Multirepo

传统的项目开发模式,比如create-react-app、vue-cli等框架模板脚手架生成的项目。

优点:

各模块管理自由度高;

各模块仓库体积一般不会太大;

缺点:

仓库分散不好找,分支管理混乱;

版本更新频繁,公共模块版本发生变化,需要对所有模块进行依赖更新;

Monorepo

优点:

统一的规范、构建工具;

方便版本管理和依赖,模块之间的引用调试都变得非常方便;

Multirepo的缺点就是它的优点。

缺点:

随着应用扩展,仓库体积将变大。

lerna+yarnworkspace应用场景

作为业务组件库的工程环境搭建。实现单个业务组件作为单独的npm包进行管理和发布,无需将各个业务组件分开建立在多个Git仓库中,且它们的技术栈、构建工具、规范等都可以保持一致。

作为日常业务项目工程管理。比如有一个低代码业务需求,低代码核心工作区的交互都相同,不同的是业务场景(外层壳子和一些定制功能),低代码相关的模块都可以复用,我们只需在这个仓库内不断去扩展业务需求即可,达到核心代码的复用(当然,可能会想到将低代码核心作为线上包)。

Lerna

Lerna是一个管理工具,用于管理包含多个软件包(package)的JavaScript项目,是Babel自己用来维护自己的Monorepo并开源出的一个项目。

它可以:

统一的一套规范、构建标准;

对相互耦合较大、相互独立的JS/Git库进行管理;

统一的工作流和CodeSharing(代码共享)。

下面我们从以下几个方面来熟悉Lerna:

Lerna管理模式;

Lerna入门指引;

Lerna管理命令;

Lerna配置文件;

Lerna应用Demo;

Lerna版本发布;

Lerna最佳实践;

Lerna注意事项。

Lerna管理模式

lerna管理项目可以使用两种模式,默认固定模式,当使用lernainit-i命令初始化项目时,此时为独立模式。(模式是用来管理多个package发包时的方式)

固定模式:在发包时会检测packages下涉及到变更的包,给这些变更的包使用同一版本,未发生变更的包不应用改版本,且不做发布升级;发布时可通过lernapublishmajor(大)|minor(中)|patch(小)自定义版本。

独立模式(常用的模式):允许每个包有自己独立的版本号,在lernapublish发布时,需要为每个改动的库指定版本号(逐个询问需要升级的版本号)。此模式,lerna.json-version字段指定为independent。

Lerna入门指引

全局安装Lerna:

npm?install?--global?lerna

初始化git代码仓库:

git?init?lerna-repo?&&?cd?lerna-repo

初始化Lerna:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files

此时得到了这样一个仓库目录结构:

lerna-repo/??packages/??package.json??lerna.json

其中packages中保存着每个独立的包模块。

安装lerna到仓库node_moles中:

npm?install

至此,我们就完成了一个Lerna工程的初始化工作,下面我们掌握一些操作命令来管理Lerna。

Lerna管理命令

lernainit将一个仓库初始化为lerna仓库(默认固定模式)。支持参数:

--independent/-i?–?使用独立的版本控制模式

lernacreate「package」创建一个package到项目工程的packages下。

lernaadd「mole」

为每个package都安装指定依赖:

lerna?add?react

为指定的package安装特定依赖:

lerna?add?react-dom?packages/package1?//?or?lerna?add?react-dom?--scope=package1

添加依赖到根目录node_moles中:

npm?install?typescript?-D

package之间的相互依赖(会在package/package.json下添加该依赖):

lerna?add?package2?--scope?package1?//?or?lerna?add?package2?packages/package1

lernapublish用于npm包版本发布,具体细节可看下文「Lerna版本发布」。

lernabootstrap用于将packages链接在一起(前提是相互依赖的库),并安装package下的依赖到package/node_moles。

注意,它不会安装根目录package.json的依赖,如果需要安装根目录依赖,请使用npminstall。

参数:

--hoist:依赖提升,把每个package下的依赖包都提升到工程根目录(删除包下的node_moles,将依赖安装在根目录,但依赖注册不会在package/package.json内删除,也不会在root/package.json内添加此依赖)

lernaclean删除各个包下的node_moles(不会删除根目录node_moles)。

lernals列出当前Lerna仓库中的所有公共软件包(publicpackages)。

lernarun「script」

运行每个包下面的script(如果某个包没有此script,将会报错)

git?init?lerna-repo?&&?cd?lerna-repo0

运行某个包下面的script

git?init?lerna-repo?&&?cd?lerna-repo0?--scope?package1

lernaexec「shell」允许去执行shell脚本

git?init?lerna-repo?&&?cd?lerna-repo2

lernachanged检查自上次发布以来哪些软件包被修改过。

lernalink链接互相引用的库,当pakcage/package.json内明确了packages下的包时,才会将相关包链接到package/node_moles中。

lernainfo查看lerna及运行环境的信息。

Lerna配置文件

在lerna.json配置文件内可以指定工作模式、packages的位置以及一些命令的默认参数定义,如下示例:

git?init?lerna-repo?&&?cd?lerna-repo3

version:当前仓库的版本,Independentmode请设置为independent;

packages:指定包所在的目录,支持指定多个目录;

npmClient:允许指定命令使用的client,默认是npm,可以设置成yarn;

useWorkspaces:使用yarnworkspaces管理Monorepo;

command.bootstrap.npmClientArgs:指定默认传给lernabootstrap命令的参数;

command.publish.ignoreChanges:指定那些目录或者文件的变更不用触发package版本的变更;

command.publish.message:执行发布版本更新时的生成的commitmessage;

command.publish.registry:指定发布到的registryurl,比如可以发布到指定私服,默认是npmjs.org;

command.publish.conventionalCommits:lernaversion将生成CHANGELOG.mdfiles(如果设置了这个,lerna管理模式将直接使用固定模式,version=independent的配置将失效)。

Lerna应用Demo

有了上面的基础使用的了解,下面我们通过一个简单Demo熟悉一下Lerna管理Packages的流程方式。

创建Lerna工程:

git?init?lerna-repo?&&?cd?lerna-repo4

创建两个package:

git?init?lerna-repo?&&?cd?lerna-repo5

在package中维护几行测试代码:

git?init?lerna-repo?&&?cd?lerna-repo6

//lerna-mole2/lib/lerna-mole2.jsconstlernaMole1=require('lerna-mole1');mole.exports=lernaMole2;functionlernaMole2(){console.log('lerna-mole2');}lernaMole1();lernaMole2();

git?init?lerna-repo?&&?cd?lerna-repo7

运行脚本:

git?init?lerna-repo?&&?cd?lerna-repo0?--scope?lerna-mole2

哎呀,此时会看到终端报错信息:

Error:Cannotfindmole'lerna-mole1'

手动建立package之间的关联:

git?init?lerna-repo?&&?cd?lerna-repo9

此时可以在lerna-mole2目录下看到生成了node_moles文件夹,并且在里面放置了和lerna-mole1一模一样的包(软链接)。

再来执行一次命令:

git?init?lerna-repo?&&?cd?lerna-repo0?--scope?lerna-mole2?终端输出:?lerna-mole1?lerna-mole2

好啦,我们第一个简单Lerna应用编写完成。接下来就是发布工作。

Lerna版本发布

packages下的包版本发布需要使用lernapublish,这个命令组合了这两个命令:lernaversion和npmpublish。

其中lernaversion针对Lerna的管理模式(固定模式和独立模式),在表现上有所不同。

但主要工作还是在进行npmpublish之前,去管理哪些包要进行发布,以及发布过程中生成的Gitcommit、Gittag的提交。

固定模式下的lernaversion:

找出从上一个版本发布以来有过变更的package;

根据当前lerna.json中的版本生成新的版本号;

更新涉及到变更package下的package.json版本号;

更新lerna.json文件中的版本号;

将version更新、生成的CHANGELOG.md文件带来的变动提交为一次commit;

基于这次commit为所有涉及到更新的package打上各自的tag;

推送commit和tags到远程仓库。

独立模式下的lernaversion:

找出从上一个版本发布以来有过变更的package;

提示开发者为需要更新的package选择(一组VersionSelect)要发布的版本号;

更新到package下的package.jsonversion版本号;

如果packages下其他包有依赖这个包,那么其他包的package.json此包版本也会更新;

将version更新、生成的CHANGELOG.md文件带来的变动提交为一次commit;

基于这次commit为所有涉及到更新的package打上各自的tag;

推送commit和tags到远程仓库。

这里需要注意一下lerna查找包变更的逻辑:

在当前分支,找到最近一次tag,将当前commit和tag进行比较,看哪些package下的文件发生了变更。

命令使用如下:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files1

初次使用发布时可能会遇到以下一些问题和注意事项:

避免开发者自己去打tag。lerna发布时会自动生成tag,并且查找更新是基于tag来识别的,避免开发者手动打上tag后,影响lerna查找变更,可能会造成一些变更包没有按照预期发布。

避免多条分支同时进行。在多条分支同时进行时,可能会生成相同的版本号,从而发生版本冲突。解决办法:分支开发者之前应提前约定好版本。

lernapublish中途发布失败,如何进行重发布。有时候发布可能会失败(比如npm没有登录、没有使用npmjs镜像源),再次运行lernapublish时,因为tag已经打上了,无法再查找到更新,进行包的发布。

可以采用下面两种发布方式:

运行lernapublishfrom-git。会将当前标签中涉及的NPM包再发布一次。(不会再更新package.json,只是执行npmpublish);

运行lernapublishfrom-package。会将当前所有本地包中的package.json和远端npm比对,如果npm上不存在此包的最新版本,都执行一次npmpublish。

Lerna最佳实践

目前业界使用最多的方案是:lerna+yarmworkspace结合的Monorepo方案,两者工作职责划分不同:

yarn处理依赖安装工作(只想做好包管理工具);

lerna处理发布流程。

此处内容可以在下文查看yarnworkspace使用指南。

Leran注意事项

发布前,提交工作区的变更。在发布前,需要提交工作区的文件变更,否则终端会收到下面报错信息:

lernaERR!EUNCOMMITWorkingtreehasuncommittedchanges,pleasecommitorremovethefollowingchangesbeforecontinuing:

发布前,需使用npmjs.org镜像。在发布前,如果npm设置的镜像源为淘宝镜像,需要切换回npm镜像:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files2

如果要发布一个Scope包:Scope是指具有“组织”的包,比如Babel的相关包都是这一格式:@babel/xxx,在发布一个具有Scope包时,需要确保Organization(组织)已在npm上创建,私有包需要收费,公共包则为免费。

在发布Scopepackage时,需要在package.json声明accesspublish:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files3

发布意外中断,进行重发布:如果发布因为某些原因中断了,未发布成功,再次执行发布,会得到如下提示:

lernasuccessNochangedpackagestopublish

但由于包并未成功发布到npmjs上,这时可以执行以下命令进行重发布:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files4

independent模式并未生效:在lerna.json下指定了version为independent,但是发布时却还是固定模式的流程,原因可能是lerna.json内配置了conventionalCommits:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files5

可以将其配置移除得到解决。

固定模式如何自己指定版本:当我们执行lernapublish时,lerna会自定分配一个版本提供我们使用;但这个版本可能不是我们期望发布的版本;如何自己控制发布的版本呢,在发布时我们可以传递配置:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files6yarnworkspace

对于Monorepo的工程,使用最多的方式是lerna结合yarnworkspace一起使用。

因为yarn在依赖管理上做的非常不错,适合我们业务场景的依赖模块管理。

而package的发布工作依旧交由lernapublish来运转。

下面我们从以下几个方面来熟悉yarnworkspace:

yarnworkspace管理工程;

yarnworkspace管理命令;

yarnworkspace入门实战。

yarnworkspace管理工程

初始化工程的步骤和上面lerna的方式一样,与lerna不同的是,需要做以下配置:

在lerna.json中声明使用yarnworkspace进行依赖管理:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files7

在root/package.json下必需包含workspaces数组,与lerna.json下的packages保持一致:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files8yarnworkspace管理命令

yarn管理命令大致分为两类(容易混淆,这里先提及一下):

处理工程下指定的包模块时使用:yarnworkspace;

处理工程根目录全局或所有包模块时使用:yarnworkspaces。

yarninstall代替npminstall+lernabootstrap安装工程依赖。

它与lernabootstarp不同的是:

yarninstall会将package下的依赖统一安装到根目录之下。这有利于提升依赖的安装效率和不同package间的版本复用(有些包是需要私有依赖的,而私有依赖会被多个包安装多次,而提升依赖可以解决这一问题)。

yarninstall会自动帮助解决安装(包括根目录下的安装)和packageslink问题。

yarnadd「mole」

为每个package都安装指定依赖:

lerna?init//?lerna?info?Creating?package.json?//?lerna?info?Creating?lerna.json?//?lerna?info?Creating?packages?directory?//?lerna?success?Initialized?Lerna?files9

为指定的package安装特定依赖:

lerna-repo/??packages/??package.json??lerna.json0

注意,package1一定是packages/package1/package.jsonname字段,有时候pa

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
Ba(NO3)2与H2SO3 反应的生成物是什么? 为什么强酸性的溶液不会产生BaSO3沉淀? 高中化学 SO2通入Ba(N03)2 某探究小组的同学用H2SO4、Ba(NO3)2、NaOH、K2CO3四种溶液进行“复分... ...3↓+2HNO3,这个反应能发生吗?好像违背了强酸制弱酸的原理。大家说... 波涛滚滚是什么动物 昆明申报灵活就业补贴条件 湖南残疾人在昆明有补贴吗 云南残疾人最低生活保障未发放怎么办 我看见别人的QQ好友里有3个自己的QQ号,怎么加的啊 go to the software and workspace center?是什么意思 1986年虎五行属什么,是什么命 为什么不建议学英语专业 就业前景和方向有哪些 求亚马逊食人族百度云资源 如何愿意学习国学经典 在网上认识的一个网友,和他处了一年的对象,他现在发了照片长得太丑了... 如果一个人在网上认识了一个女孩,但是这个人就是发的照片不是他... 阅读国学经典的好处 如何拒绝网上女生的追求? 奔跑吧兄弟电影在哪看不要钱 奔跑吧兄弟免费观看或下载的网页有没有,复制给我,谢谢谢 奔跑吧,兄弟离线观看怎么下载? 一种布料先提价10%,后来又降价10%,现价()过程,每选项都要算(有的选项... 钢铁雄心傀儡国资料 ...动画片,讲得是在南极的企鹅一家的故事,是用橡皮泥捏... 电磁炉显示01是怎么回事? 知了的叫声可以用什么词形容? 浏览器中的MIME类型 大枣出不完可以做成哪些美食? HTTP解惑-Content-Type 坚持晚上不吃饭会瘦吗 下午不吃饭睡觉会不会瘦 am集团简介 哪个外汇平台是比较灵活的呢,最好资金可以随存随取的那种。 广州磐志网络科技有限公司发展简史 Am Bank(M) Berhad是什么银行? 汇款的话在上海应该怎么汇? 有没有什... 德胜家具的发展简史 建大卡需要什么资料 建大卡需要的资料 瑞士杜卡斯贝和英国AM外汇哪个比较好呢,不知道要投资哪个? 英国AM外汇平台的pro和standard都有哪些不同之处啊? 毛手毛脚代表生肖 qq邮箱帐号密码都填了就是通不了,总提示电脑开通,怎么办新手首次开通... ...之后头晕,过一会眼前一片黑,暂时没有知觉,晕倒过两次,为什么??_百 ... 突然问恶心头晕晕倒时全身无力头脑清醒只有一分钟就好了好了之后还是... 阿胶的正确吃法服用时间 ...无故冻结,上面显示输入手机号接收解冻验证码,可是输入路人号码收不到... 为什么暴风影音打开一集rmvb电影就卡住了 脑血栓问题:我妈妈昨天突然晕倒(第一次),四肢无力,头晕,呕吐,说话不... 突然间头晕,不伴随头痛,不是块晕倒那么强烈,小程度的眩晕,但持续时间有... 2023年国庆节那天是星期几2023年国庆节是哪一天