前端工程师应该知道的yarn知识
yarn 是在工作中离不开的工具,但在工作中,很多人基本只会使用 yarn install,而且会手动删除 node-modules,或删除 yarn.lock 文件等不规范操作。本文将从一些基础的知识点开始介绍,循序渐进的让你对 Yarn 有一个更深入的了解,来保证规范的使用yarn,避免一些隐藏bug的产生。
本文主要介绍以下知识:
- 什么是registry
- 依赖的版本含义及写法
- 依赖类型及区别(
devDependences,devDependences,peerDependences,optionalDependencies,bundledDependencies)- 缓存介绍
yarn.lock文件作用及介绍
yarn install安装依赖的过程- 依赖关系树的模块扁平化
- 常用的
yarn命令介绍
什么是registry
registry是 模块仓库提供了一个查询服务,也就是我们常说的源。以yarn官方镜像源为例,它的查询服务网址是https://registry.yarnpkg.com。
这个网址后面跟上模块名,就会得到一个 JSON 对象,里面是该模块所有版本的信息。比如,访问 https://registry.npmjs.org/vue,就会看到 vue 模块所有版本的信息。
registry 网址的模块名后面,还可以跟上版本号或者标签,用来查询某个具体版本的信息。
https://registry.yarnpkg.com/vue/2.6.10
上面返回的 JSON 对象里面,有一个dist.tarball属性,是该版本压缩包的网址。dist.shasum 属性相当于hash值,在lock和缓存时会使用到,下文会提到。
dist: {
  "shasum": "a72b1a42a4d82a721ea438d1b6bf55e66195c637",
  "tarball":"https://registry.npmjs.org/vue/-/vue-2.6.10.tgz"
},
复制代码我们在执行 yarn install 时,就是向 registry 查询得到上面的压缩包地址进行下载的。
工作中,我们可能有需要修改镜像源的场景,比如修改成淘宝源或者自己公司的私有源。
查看和设置源,可以通过 yarn config 命令来完成
查看当前使用的镜像源
yarn config get registry
复制代码修改镜像源(以修改成淘宝源为例)
yarn config set registry https://registry.npm.taobao.org/
复制代码依赖版本
yarn的包遵守 semver,即语义化版本。 SemVer 是一套语义化版本控制的约定,定义的格式为
X.Y.Z(主版本号.次版本号.修订号):
X.主版本号:进行不向下兼容的修改时,递增主版本号
Y.次版本号: 做了向下兼容的新增功能或修改
Z.修订号:做了向下兼容的问题修复
复制代码yarn 中依赖版本范围的表示方法有以下几种:
- 通过比较器
| 表示 | 含义描述 | 
|---|---|
| <2.0.0 | 任何小于 2.0.0 的版本 | 
| <=3.1.4 | 任何小于或等于 3.1.4 的版本 | 
| >0.4.2 | 任何大于 0.4.2 的版本 | 
| >=2.7.1 | 任何大于或等于 2.7.1 的版本 | 
| =4.6.6 | 任何等于 4.6.6 的版本 | 
| >=2.0.0 <3.1.4 | 交集,大于或等于 2.0.0 并小于 3.1.4 | 
| <2.0.0 || >3.1.4 | 并集 小于 2.0.0 或者大于 3.1.4 | 
如果没有指定运算符,默认为 =
- 通过连字符
| 表示 | 含义描述 | 
|---|---|
| 2.0.0 - 3.1.4 | >=2.0.0 <=3.1.4 | 
| 0.4 - 2 | >=0.4.0 <=2.0.0 | 
版本号中缺少的那些部分会用数字 0 填充。
- X范围
 字符 X、x 或者 * 都可以作为通配符,用于填充部分或全部版本号。
 被省略的那部分版本号默认为 x 范围。
| 表示 | 含义描述 | 
|---|---|
| * | >=0.0.0 (任意版本) | 
| 2.x | >=2.0.0 <3.0.0(匹配主要版本) | 
| 3.1.x | > = 3.1.0 < 3.2.0(匹配主要和次要版本) | 
| ``(空字符串) | * 或 > = 0.0.0 | 
| 2 | 2.x.x 或 > = 2.0.0 < 3.0.0 | 
| 3.1 | 3.1.x 或 > = 3.1.0 < 3.2.0 | 
- ~ 字符范围
 同时使用字符 ~ 和次版本号,表明允许修订号变更。同时使用字符 ~ 和主版本号,表明允许次版本号变更。
| 表示 | 含义描述 | 
|---|---|
| ~3.1.4 | >=3.1.4 <3.2.0 | 
| ~3.1 | 3.1.x 或 > = 3.1.0 < 3.2.0 | 
| ~3 | 3.x 或 > = 3.0.0 < 4.0.0 | 
- ^ 字符范围
 字符 ^ 表明不会修改版本号中的第一个非零数字,3.1.4 里的 3 或者 0.4.2 里的 4。版本号中缺少的部分将被 0 填充,且在匹配时这些位置允许改变。
| 表示 | 含义描述 | 
|---|---|
| ^3.1.4 | >=3.1.4 <4.0.0 | 
| ^0.4.2 | >=0.4.2 <0.5.0 | 
| ^0.0.2 | >=0.0.2 <0.0.3 | 
使用 yarn add [package-name] 命令安装依赖,默认使用的是 ^ 范围。
需要注意的是,如果一个比较器包含有预发布标签的版本,它将只匹配有相同 major.minor.patch 的版本。
例如 >=3.1.4-beta.2,可以匹配 3.1.4-beta.3,但不会匹配 3.1.5-beta.3 版本。
依赖类型
dependences 代码运行时所需要的依赖,比如vue,vue-router。
devDependences 开发依赖,就是那些只在开发过程中需要,而运行时不需要的依赖,比如babel,webpack。
peerDependences 同伴依赖,它用来告知宿主环境需要什么依赖以及依赖的版本范围。
如果宿主环境没有对应版本的依赖,在安装依赖时会报出警告。
比如包 eslint-plugin-import 中有依赖:
 "peerDependencies": {
    "eslint": "2.x - 5.x"
  },
复制代码在install时,如果宿主环境没有 2.x-5.x 版本的 eslint,cli就会抛出警告。但不会自动帮我们安装,仍然需要手动安装。
optionalDependencies 可选依赖,这种依赖即便安装失败,Yarn也会认为整个依赖安装过程是成功的。
可选依赖适用于那些即便没有成功安装可选依赖,也有后备方案的情况。
bundledDependencies 打包依赖,在发布包时,这个数组里的包都会被打包打包到最终的发布包里,需要注意 bundledDependencies 中的包必须是在devDependencies或dependencies声明过的。
缓存
yarn 会将安装过的包缓存下来,这样再次安装相同包的时候,就不需要再去下载,而是直接从缓存文件中直接copy进来。
可以通过命令 yarn cache dir 查看yarn的全局缓存目录。我的缓存目录在 /Library/Caches/Yarn/v1 下。
可以看出,yarn 会将不通版本解压后的包存放在不同目录下,目录以
npm-[package name]-[version]-[shasum]`
复制代码来命名。shasum 即上文中 registry 获取的 dist.shasum。
我们可以通过命令查看已经缓存过的包。
yarn cache list    列出已缓存的每个包
yarn cache list --pattern <pattern>  列出匹配指定模式的已缓存的包
复制代码例如执行 yarn cache list --pattern vue
yarn.lock
yarn.lock 中会准确的存储每个依赖的具体版本信息,以保证在不同机器安装可以得到相同的结果。
下面以@babel/code-frame为例,看看yarn.lock 中会记录哪些信息。
- 第一行 "@babel/code-frame@7.0.0-beta.54"包的name和语义化版本号,这些都来自package.json中的定义。
- version字段,记录的是一个确切的版本。
- resolved字段记录的是包的URL地址。其中hash值,即上文的- dist.shasum。
- dependencies字段记录的是当前包的依赖,即当前包在- package.json的- dependencies字段中的所有依赖。
Yarn 在安装期间,只会使用当前项目的 yarn.lock 文件(即 顶级 yarn.lock 文件),会忽略任何依赖里面的 yarn.lock 文件。在顶级 yarn.lock 中包含需要锁定的整个依赖树里全部包版本的所有信息。
yarn.lock文件是在安装期间,由 Yarn 自动生成的,并且由yarn来管理,不应该手动去更改,更不应该删除yarn.lock文件,且要提交到版本控制系统中,以免因为不同机器安装的包版本不一致引发问题。
Yarn install过程
首次执行 yarn install 安装,会按照 package.json 中的语义化版本,去向 registry 进行查询,并获取到符合版本规则的最新的依赖包进行下载,并构建构建依赖关系树。 比如在 package.json 中指定 vue 的版本为 ^2.0.0,就会获取符合 2.x.x 的最高版本的包。然后自动生成 yarn.lock 文件,并生成缓存。
之后再执行 yarn install,会对比 package.json 中依赖版本范围和 yarn.lock 中版本号是否匹配。
- 版本号匹配,会根据 yarn.lock中的resolved字段去查看缓存, 如果有缓存,直接copy,没有缓存则按照resolved字段的url去下载包。
- 版本号不匹配,根据 package.json中的版本范围去registry查询,下载符合版本规则最新的包,并更新至yarn.lock中。
模块扁平化
上面提到,在安装依赖时,会解析依赖构建出依赖关系树。 比如我项目的首层依赖(即当前项目的dependence和devDependences中的依赖,不包括依赖的依赖)中有A,B,C三个包,A 和 B包同时依赖了相同版本范围的D包。那么这部分的依赖关系树是这样的:
├── A
│ └── D
├── B
│ └── D
├── C
复制代码如果按照这样的依赖关系树直接安装的话,D模块会在A包和B包的 node_modules中都安装,这样会导致模块冗余。
为了保证依赖关系树中没有大量重复模块,yarn在安装时会做dedupe(去重)操作,它会遍历所有节点,逐个将模块放在根节点下面,也就是当前项目的 node-modules 中。当发现有相同的模块时,会判断当前模块指定的 semver 版本范围是否交集,如果有,则只保留兼容版本,如果没有则在当前的包的 node-modules 下安装。
所以上面的说的情况,最终安装完成是下面这样的,A,B,C,D包都会安装在第一层 node-modules 下。
├── A
├── B
├── C
├── D
复制代码如果A包和B包依赖的是不兼容的版本,假设A包依赖的是D@1版本的包,B包依赖的是D@2版本。则最终安装的结果如下:
├── A
├── B
│ └── D@2
├── C
├── D@1
复制代码当代码中 require 或 import 某个模块时,会从当前 package 的 node-modules 里中开始找,找不到就到当前package的上一层 node-modules 里找,这样一直找到全局的node_modules。 所以上面的安装的树结构,可以保证每个 package 都能获取到所需要版本的包。
常用的yarn命令
- yarn install 安装依赖
yarn install / yarn  在本地 node_modules 目录安装 package.json 里列出的所有依赖
yarn install --force 重新拉取所有包,即使之前已经安装的(所以以后别在删除node-modules了...)
yarn install --modules-folder <path> 为 node_modules 目录指定另一位置,代替默认的 ./node_modules
yarn install --no-lockfile 不读取或生成 yarn.lock 文件
yarn install --production[=true|false] / --production / --prod 只安装 dependence下的包,不安装 devDependencies 的包
复制代码- yarn add
yarn add package-name 会安装 latest 最新版本。
yarn add <package...>  安装包到dependencies中
yarn add <package...> [--dev/-D]  用 --dev 或 -D 安装包到 devDependencies
yarn add <package...> [--peer/-P]  用 --peer 或者 -P 安装包到 peerDependencies
yarn add <package...> [--optional/-O] 用 --optional 或者 -O 安装包到 optionalDependencies
yarn add <package...> [--exact/-E] 用 --exact 或者 -E 会安装包的精确版本。默认是安装包的主要版本里的最新版本。 比如说, yarn add foo@1.2.3 会接受 1.9.1 版,但是 yarn add foo@1.2.3 --exact 只会接受 1.2.3 版。
yarn add <package...> [--tilde/-T]  用 --tilde 或者 -T 来安装包的次要版本里的最新版。 默认是安装包的主要版本里的最新版本。 比如说,yarn add foo@1.2.3 --tilde 会接受 1.2.9,但不接受 1.3.0。
复制代码- yarn config 管理配置文件
yarn config get <key> 查看配置key的值
yarn config list 查看当前的配置
yarn config delete <key> 从配置中删除配置key
yarn config set <key> <value> [-g|--global] 设置配置项 key 的值为 value
复制代码- 其他常用命令
yarn list 查询当前工作文件夹所有的依赖
yarn info <package> [<field>]  查看包信息,可以查看特定
yarn remove <package...>  从依赖里移除名包,同时更新你 package.json 和 yarn.lock 文件。
yarn <script> [<args>] 执行用户自定义的脚本
复制代码- 详细日志模式 运行yarn命令时,增加参数 --verbose,这对排查错误时很有帮助
yarn <command> --verbose
链接:https://juejin.im/post/5da9c6b0e51d4524d67486e2
前端工程师应该知道的yarn知识的更多相关文章
- 15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码)
		15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码) 前言 设计模式是一个程序员进阶高级的必备技巧,也是评判一个工程师工作经验和能力的试金石.设计模式是程序员多年工作经 ... 
- 前端工程师需要掌握的 Babel 知识
		在前端圈子里,对于 Babel,大家肯定都比较熟悉了.如果哪天少了它,对于前端工程师来说肯定是个噩梦.Babel 的工作原理是怎样的可能了解的人就不太多了.本文将主要介绍 Babel 的工作原理以及怎 ... 
- 前端必须知道的 Nginx 知识
		Nginx一直跟我们息息相关,它既可以作为Web 服务器,也可以作为负载均衡服务器,具备高性能.高并发连接等. 1.负载均衡 当一个应用单位时间内访问量激增,服务器的带宽及性能受到影响, 影响大到自身 ... 
- 每个开发人员都应该知道的WebSockets知识
		转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://blog.bitsrc.io/deep-dive-into-websockets- ... 
- 前端开发者应该知道的 CSS 小技巧
		一些小技巧让你的CSS技术更专业 使用:not()去除导航上不需要的边框 为body添加行高 垂直居中任何元素 逗号分离的列表 使用负nth-child选择元素 使用SVG图标 文本显示优化 在纯CS ... 
- Linux系统管理员应该知道的journalctl知识
		在Systemd出现之前,Linux系统及各应用的日志都是分别管理的,Systemd开始统一管理了所有Unit的启动日志,这样带来的好处就是可以只用一个 journalctl命令,查看所有内核和应用的 ... 
- 作为一个有B格的前端工程师需要掌握的一些知识
		如果说你3年还在不停地切页面的... 那么你对http协议的了解程度 你的原生的javascript的掌握程度 你的页面的优化的理念 你在写页面是否会有什么独特地技巧 你对ajax的get和post方 ... 
- Spring Boot 学习前你应该知道的 Maven 知识
		Maven 是什么? 回答这个问题,我们先来了解下没有Maven,我们是怎么使用开发者工具IDE去开发Java程序的.我之前开发Java程序不多,但是我还是记得,我是从网上下载或从合作方拷贝 jar ... 
- 2015 前端[JS]工程师必知必会
		2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ... 
随机推荐
- docker实战之通过nginx镜像来部署静态页
			本章我们主要讲解如何通过docker构建一个nginx容器,这里我们以部署一个静态html为素材来进行演示. 首先我们通过[docker search nginx]命令来查找Docker Hub上的n ... 
- mysql CONCAT函数
			有时候我们需要使用coacat函数拼接一些字段的生成一个字符串,比如:select concat(field1,field2,field3) from xxx: 这时候我们就会的到一个这些字段的值拼 ... 
- 一个数据库操作类,适用于Oracle,ACCESS,SQLSERVER
			最近做了一个数据诊断的项目,里面自己写了一个数据库的操作类,包含:连接数据库.读数据表.执行SQL操作,释放数据库等组成,希望对大家有用,由于水平有限,若有错误或者代码不足地方欢迎指正,谢谢. ADO ... 
- Centos - php5.4升级到7.1 yum安装
			查看当前 PHP 版本 1 php -v 查看当前 PHP 相关的安装包,删除之 1 2 3 4 5 yum list installed | grep php yum remove php ... 
- django 后台静态文件不显示
			原文链接 https://my.oschina.net/VASKS/blog/874270 django admin svg 不显示.后台显示 xx.svg 200 但浏览器就是不显示. 百度了一圈, ... 
- [Oracle]关于回滚段的一些转贴摘录
			ORACLE 回滚段 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段 ... 
- Http的请求协议请求行介绍
			请求协议包含的内容 请求行 GET /day04-tomcat/index.jsp HTTP/1.1 HTTP/1.1: 表示的是我们使用的是http协议的1.1版本 请求头 请求空行 请求体: 存储 ... 
- 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_12.RabbitMQ研究-工作模式-统配符工作模式测试
			路由模式: 1.每个消费者监听自己的队列,并且设置带统配符的routingkey. 2.生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列. 创建测试用例 交换机的名 ... 
- [Bayes] *Bayesian Classifier for Face Recognition
			Bayesian在识别领域的贡献,着实吸引人 阅读笔记 Gabor特征 (简介,另单独详述) 通过上面的分析,我们知道了,一个Gabor核能获取到图像某个频率邻域的响应情况,这个响应结果可以看做是图像 ... 
- 程序间获取ALV显示数据(读取ALV GRID上的数据)
			程序间获取ALV数据的两种方法: 方法1:通过修改SUBMIT的目标程序,把内表EXPORT到内存,SUBMIT后IMPORT ,该方法需要修改目标程序,可以任意设置目标程序的中断点: * Execu ... 
