当前位置: 首页 > 后端技术 > Node.js

Yarn2.0介绍

时间:2023-04-03 17:31:12 Node.js

Yarn作为强大的JavaScript生态依赖管理工具,于今年1月24日正式发布了v2版本。在本文中,我将向大家介绍以下内容:为什么要开发v2版本?v2有什么新特性?Yarn的未来计划要从v1迁移到v2,请参阅迁移。为什么要开发v2版本?原有的代码架构无法满足新的需求。Yarn诞生于2016年初,一开始大量借鉴了npm,其架构设计本身也不太符合Yarn开发者的愿景。之后,由于不断有新的需求,Yarn在接下来的几年里增加了许多新特性,包括Workspaces(2017)、Plug'n'Play(2018)和Ziploading(2019)。这些新概念在Yarn刚创建的时候根本不存在,所以Yarn的架构设计没有考虑到日后这些新特性的加入,所以随着时间的推移,Yarn的代码越来越难以维护和扩展.由于这个技术原因,Yarn需要更现代的代码结构来满足新需求的开发。鼓励开发者贡献代码Yarn作为一个社区项目,秉承一个理念:我们不想为你工作,我们想和你一起工作。由此可见,Yarn的开发者其实是希望有更多的开发者参与到这个项目的开发中来,而不是只有他们维护。为了降低开发者向Yarn项目贡献代码的门槛,Yarnv2版本做了如下改动:从Flow迁移到现在更流行的TypeScript作为开发语言,让开发者用更熟悉的技术贡献代码堆。基于插件的模块化(Modular)代码架构允许开发者在不了解Yarn核心代码的情况下,通过实现插件的方式为Yarn添加新的功能。而且Yarn的核心功能也是通过内置不同的插件来实现的,这与Webpack的设计思路如出一辙,开发者可以很容易的理解各个功能是如何实现的。v2有什么新特性?说完为什么要开发v2版本,我们再来看看它有哪些新特性。更具可读性的输出日志虽然Yarn的输出日志的可读性相对于其他替代方案(比如npm)来说是比较高的,但是它仍然存在着各种各样的问题,比如当输出信息特别多的时候,有时候开发者很难找到有用的内容在大量的输出中,输出日志的颜色并不能帮助用户快速识别重要信息,甚至会对日志的阅读造成一定的干扰。基于这些原因,v2版本对输出日志做了一些改进。我们先来看看长什么样子:从上面的输出中,我们可以看到一个错误号(errorcode),不同错误号的含义可以在这个文档中找到。这些错误编号可以让开发者快速定位错误并更容易地搜索解决方案来修复错误。除了增加错误编号外,输出日志的颜色也有了很大的改善。例如,在上面的输出中,会使用鲜艳的颜色来突出显示依赖名称及其版本号,这使得开发人员更容易获得有用的信息。Yarndlxyarndlx的功能类似于npx。dlx是下载和执行的缩写。此命令将在本地创建一个临时环境以下载指定的依赖项。依赖下载完成后,会在当前工作目录(cwd)执行依赖中包含的可执行二进制文件。该临时空间将在命令完成后被删除,因此这些操作都是一次性的。yarndlx命令不会改变当前项目的package.json的内容,而且只能执行远程脚本不能执行本地脚本(本地脚本可以用yarnrun执行),所以比npxsecurity的价值更高。由于v2版本默认开启了Plug'n'Play功能,当你使用yarndlx命令执行远程脚本时,脚本的依赖会缓存在本地环境中,这样再次执行时就不会需要下载依赖,所以它的速度会变得非常快。Betterworkspacessupportv2版本最大的变化之一是将workspaces变成一等公民(first-classcitizens),这样可以更好地支持monorepo的开发。v2版本在以下几个方面支持workspaces:yarnadd添加交互模式(interactivemode)如果想在项目的某个workspace中引入某种依赖,可能要考虑其他workspace是否也使用了这个依赖,而Avoid引入不兼容的版本。在v2版本中,可以通过-i参数让yarnadd命令进入交互模式,yarn会帮你检查这个依赖是否在其他工作区被使用,让你选择是否在其他工作区复用依赖版本或使用其他版本。所有工作区的某个依赖版本的v2版本中添加了一个新的yarnup命令。该命令类似于yarnupgrade命令,用于更新依赖版本。与yarnupgrade不同的是,它可以同时更新所有工作空间的依赖版本,无需切换到每个工作空间运行更新命令。该命令还有一个交互模式-i允许您确认在不同工作空间中执行的特定操作。关联工作区自动发布参与过monorepo开发的同学一定遇到过这样一个问题:当某个包(工作区)发布新版本时,要发布其他关联包非常麻烦。如果你在你的项目中使用了Lerna,当你发布一个包的新版本时,你要么必须发布所有包的新版本,要么你必须自己手动管理其他包的版本发布。虽然自己管理其他包的发布也是可以的,但是人为的事情肯定会有疏忽,多人协作的项目会让人头疼。为了解决这个问题,Yarnv2版本采用了与Lerna等同类工具完全不同的解决方案。它把这部分逻辑放在一个单独的插件中,叫做version。版本插件允许你将部分包版本管理工作分发给你的代码贡献者,它还提供了一个友好的交互界面,让你可以非常轻松地管理关联包的发布:在多个工作区中运行相同的命令是在同一项目的不同工作区中运行相同的命令是很常见的。Yarnv2版本为每个命令提供了一个新的yarn工作区,允许您在多个工作区中运行相同的命令。该命令由其内置的workspace-tools插件提供支持,例如,下面的命令将在所有工作空间中运行构建命令:同一个项目要遵循一定的规则,比如所有工作空间不能使用下划线作为依赖,或者所有工作空间依赖的包版本必须相互兼容。v2版本有一个新的概念叫做约束(Constraints),这里的约束就是对项目中各个工作空间的package.json的约束,就像ESLint对JS文件的约束一样,它会破坏工作空间的package.json一些规则给出您的错误消息,并可以帮助您修复其中的一些错误消息。Yarn的约束规则是用Prolog语法编写的。要给你的工作空间添加约束,你首先要导入约束插件:yarnpluginimportconstraints然后在项目根目录下定义一个constraints.pro文件来存放约束规则,最后在这个文件中定义你想要的约束,例如,以下约束将禁止所有工作区使用下划线作为依赖项:gen_enforced_dependency(WorkspaceCwd,'underscore',null,DependencyType):-workspace_has_dependency(WorkspaceCwd,'underscore',_,DependencyType)。定义好约束规则后就可以使用yarnconstraintscheck命令来验证项目的工作空间是否满足定义的约束规则。当出现错误时,可以使用yarnconstraintsfix命令自动修复那些可以自动修复的错误。像查询数据库一样查询工作空间的依赖信息。yarnconstraintsquery命令可以查询项目中工作空间使用的依赖信息。例如,以下命令将输出每个工作区使用的lodash版本信息:$my-project:yarnconstraintsquery"workspace_has_dependency(Cwd,'lodash',Range,_)."?YN0000:┌Cwd='packages/backend'?YN0000:└Range='4.17.0'?YN0000:┌Cwd='packages/frontend'?YN0000:└Range='4.17.0'?YN0000:Donewithwarningsin0.03s个人感觉上面依赖查询非常类似于MySQL数据库中使用SELECT语法查询数据库,是一个非常强大和实用的功能。依赖零安装(Zero-Installs)依赖零安装更像是一个概念而不是一个功能。它的想法是希望我们在使用git更新代码后,不需要每次都使用yarninstall命令去更新本地仓库的依赖。以提高开发效率,避免一些问题。它的具体做法是让开发者将本地的依赖包提交到远程的git仓库。看到这里,你可能会想:“不就是提交node_modules吗?这种做法很愚蠢!”。确实,如果直接把node_modules提交到远程仓库,每次提交都是噩梦,因为node_modules里面的文件很多(几万个文件很常见),一来你的上传下载速度会变得很慢,二来,会很慢。影响他人审查您的代码。为了解决这个问题,v2版本默认开启了即插即用+zip加载功能。启用该功能后,你的项目将不再有node_modules文件夹,所有的依赖都会被压缩成一个文件放在特定的地方,由于压缩包体积小,包数也不多,所以上面提到的node_modules不会有问题。但是为什么要依赖零安装呢?这是因为它有以下好处:更好的开发体验你不需要每次使用gitpull、gitcheckout、gitrebase命令更新你的代码时都使用yarninstall安装依赖,这样可以避免一些问题,例如,有人更新依赖版本后,如果你不执行相应的更新,你的代码就会挂掉。当审查代码时,更清楚哪些依赖项发生了变化。更快、更简单、更稳定的CI部署由于yarninstall每次部署代码都需要花费大量的时间,去掉这个步骤后,部署速度会大大提升。本地运行不会有问题,但是发布线上环境就挂了。您不需要在CI文件中配置一些安装依赖项。想看pnp+zip加载实际效果的同学可以看看yarnv2版本的【代码】(https://github.com/yarnpkg/be...,可以看到是在自己的仓库.Yarn其所有依赖都存放在/cache目录下:新协议Yarnv2版本增加了两个新协议:patch和portal协议。不知道什么是协议的同学可以看看官网的介绍。它可能用于告诉yarn如何解析package.json文件中定义的依赖项。补丁协议在我们日常的开发中,有时我们需要更改某个依赖的原始代码来做一些实验性的事情。这时候,我们就可以使用这个补丁协议。先来看看如何使用:{"dependencies":{"left-pad":"patch:left-pad@1.3.0#./my-patch.patch"}}left在上面定义package.json-pad的依赖是如何解析的,我们可以看到left-pad的解析其实是使用了patch协议,也就是说项目中使用的left-pad代码是叠加在1.3.0版本的代码上的./my-patch.patch这个patch,所谓patch就是我们自己对left-pad库的代码进行修改,类似于gitdiff文件。Portal协议Portal协议类似于原始链接协议。它的作用是告诉yarn项目中的一个依赖指向本地文件系统中的一个软链接(symlink),这个其实和yarnlink的作用类似。与链接协议不同的是,入口指向一些包(package),也就是有package.json文件的文件夹,yarn会解析这个包中的传递依赖。更具体的门户协议和链接协议的区别,请参考官方文档。规范化shell脚本(Normalizedshell)v2版本对Windows开发环境有更好的兼容性。你之前可能遇到过这样的问题:你在package.json中定义的脚本命令在OSX系统上可以运行,但是在windows电脑上就会报错。出现这个问题的原因是你在package.json中定义的脚本最终是通过Yarn创建一个子进程来执行的,而子进程的shell环境在Windows和OSX环境下是不一样的(比如文件路径的写法是不同的。相同)。为了解决这个问题,Yarnv2自带了一个简单的shell解释器(interpreter),用来兼容Windows和OSXshell环境的差异。它覆盖了90%常用的shell脚本,所以通常你定义的shell脚本在Windows环境和OSX环境下这个解析器的兼容下可以正常运行:{"scripts":{"redirect":"node./something.js>hello.md","no-cross-env":"NODE_ENV=prodwebpack"}}模块化代码架构如前所述,Yarnv2版本已经转变为模块化架构,并且支持用户自定义Plugin以增强其功能。自定义插件可以获得Yarn解析的依赖树信息和一些其他的上下文信息,所以很容易实现Lerna、Femoto、Patch-Package等一些库。想感受Yarn插件是如何实现的同学可以看看typescript插件的官方实现。这个typescript插件对于使用Typescript开发的同学来说非常有用。它可以在你使用yarnadd命令添加依赖的时候添加依赖对应的@types/package,这样可以避免很多手工工作。有关插件的更多信息,您可以查看本教程。其他更新除了上面提到的新属性,v2版本还有以下更新:Peerdependencies也可以在yarnlink中使用Lockfile格式,改为标准的YAML格式。packages只能依赖package.json中声明的那些,不允许require那些未声明的依赖规范化配置文件...想查看v2版本所有更新的朋友可以阅读Ma?lNison的文章-IntroducingYarn2或者直接查看其变更日志。Yarn未来计划v1的最后一个版本v1.22已经发布,作者将不再对v1代码添加任何新功能。Yarn的所有新功能只会在v2版本的代码库上开发。v1代码仓库将从yarnpkg/yarn迁移到yarnpkg/legacy。这个仓库会持续开放一段时间,修复一些bug,过一两年就可以实现。v2版本的代码由于历史问题不会迁移到yarnpkg/yarn,未来很长一段时间会保留在yarnpkg/berry。v1官网将迁移到legacy.yarnpkg.com,yarnpkg.com官网内容已经是v2版本next.yarnpkg.com的内容。在npm仓库中,legacy标签指向最新的v1版本代码,latest标签会持续几周指向最新版本的v1代码,然后再指向v2代码。berry标签将始终指向最新版本的v2版本。今年4月左右,Node14版本的Docker镜像可能会默认自带一个v2版本,这样就可以直接在容器中使用v2的功能了。参考Yarnberry官方文档【Yarn2-Reinventingpackagemanagement-Ma?lNisonaka@arcanisat@ReactEurope2019】(https://www.youtube.com/watch...IntroducingYarn2!个人技术动态文章首发于我欢迎关注公众号Aggression的个人博客,一起学习成长