Skip to main content

yarn

Get started

macOS

  1. 使用脚本安装,每次安装的都是最新版:
curl -o- -L https://yarnpkg.com/install.sh | bash

如需升级,再次运行此命令,然后会出现以下信息:

/Users/xxx/.yarn already exists, possibly from a past Yarn install.
> Remove it (rm -rf /Users/xxx/.yarn) and run this script again.

根据提示,由于已经安装了 yarn,所以需要先删除~/.yarn文件,然后再重新执行该命令,即可安装最新版 yarn。

  1. 通过Homebrew安装:
brew install yarn
# upgrade yarn
brew upgrade yarn

安装过程中会安装很多依赖包,也包括 nodejs,要确保 Homebrew 连接流畅,国内可以使用 ustc 镜像进行加速:

note

1, 2 安装方式的好处就是如果使用nvm管理node的版本,那么每次对node进行版本升级之后,无需重新安装yarn,但安装的时候可能会稍微慢点。

  1. 通过npm安装/升级最新版本:
npm install -g yarn@latest

可以查看 yarn 历史版本:

npm view yarn versions --json

安装指定版本的 yarn:

npm install -g yarn@1.19.2
note

如果使用nvm管理node的版本,那么每次对node进行版本升级之后,都需要重新安装yarn,因为通过 npm i -g 方式安装的全局包和 node 版本挂钩,导致全局包全部丢失。不过,通过 yarn global add 方式添加的全局包不会丢失,对应包的 bin cli 也可以正常使用,原因参考 yarn global

Windows

  1. 下载最新的.msi 文件,点击这里下载,跟随指引安装即可。

  2. 通过Chocolatey安装。Chocolatey 是一个 Windows 专用的软件包管理工具,请按照此说明安装Chocolatey。安装成功后,在控制台执行如下命令安装 yarn:

choco install yarn

更新 yarn:

choco update yarn
  1. 通过Scoop安装。Scoop是一个用于 Windows 的基于命令行的安装工具。 请按照此说明安装Scoop。安装Scoop后,在控制台执行如下命令安装yarn
scoop install yarn

更新 yarn:

scoop update yarn

Check installation

yarn --version

安装成功会显示对应的版本号:

1.19.2

Uninstall yarn

  1. 如果是 npm 安装的,则可通过命令npm uninstall yarn -g卸载 yarn
  2. 可通过yarn global bin命令找到 yarn 全局安装的根目录,然后删除 yarn 文件夹即可
rm -rf /usr/local/bin/yarn
  1. 如果是通过Chocolatey安装的,可以通过choco uninstall yarn命令卸载 yarn
  2. 如果是通过Scoop安装的,可以通过scoop uninstall yarn命令卸载 yarn

yarn init

初始化一个新项目

yarn add

新增一个依赖,添加到 package.json 文件的dependencies属性中

yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]
tip

yarn add [package] 默认添加的是 ^ 符号,详情见 Package Version

加上参数--dev或者-D,添加package依赖到devDependencies属性中

yarn add [package] --dev
yarn add [package] -D

加上参数--peer或者-P,添加package依赖到peerDependencies属性中

yarn add [package] --peer
yarn add [package] -P

加上参数--optional或者-O,添加package依赖到optionalDependencies属性中

yarn add [package] --optional
yarn add [package] -O

See more: https://yarnpkg.com/cli/add

yarn remove

移除依赖包

yarn remove [package]

yarn install

安装 package.json 文件里定义的所有依赖包

yarn

或者

yarn install

yarn cache

列出匹配指定模式的已缓存的包

yarn cache list [--pattern]

打印出当前的 yarn 全局缓存在哪里

yarn cache dir

清除全局缓存,下次运行 yarn 或者 yarn install 时会重新填充

yarn cache clean

yarn config

yarn config set <key> <value> [-g|--global]

例如设置镜像源为淘宝镜像:

yarn config set registry http://registry.npm.taobao.org

例如修改 package.json -> scripts 中运行的 shell,比如 "start": "source variables.sh; node app.js",因为 Unix-like OS 默认是 /bin/sh,用该配置指明 shell 可以保证不同机器上运行 source 命令不会出错:

yarn config set script-shell /bin/bash
tip

配置也可以放在项目的 .yarnrc.npmrc 文件中。

其他常用命令:

yarn config get <key>
yarn config delete <key>
yarn config list # Displays the current configuration.

yarn create

从任何 create-* 初学者工具包创建新项目

yarn create <starter-kit-package> [<args>]

这个命令包含两个功能:

  1. 安装工具包,或者更新包到最新版本

  2. 执行新手工具包package.jsonbin字段指向的程序,并向他转发所有的<args>

yarn create react-app my-app命令为例,它等价于:

yarn global add create-react-app
create-react-app my-app

yarn global

yarn global 是一个命令前缀,可用于 addbinlistremove 等命令,在原有行为基础上用一个全局目录来存储包

tip

与 npm 不同,在 yarn 中global参数必须紧跟在 yarn 后才能将依赖全局添加,即必须为yarn global add package-name的形式。如果写为yarn add global package-name的形式,会把名为 globalpackage-name 的包添加到本地,而非全局添加 package-name

通过 yarn 安装的全局包(无论 yarn 的安装方式),会放在~/.config/yarn/global/node_modules里面。

# if has installed global packages via yarn
$ ll ~/.config/yarn/global
node_modules
package.json
yarn.lock

yarn global bin 查看 yarn 全局安装的 bin 文件夹地址:

$ yarn global bin
/usr/local/bin
$ ll

如上图 pm2 被安装在了全局,在 cli 中输入 pm2 将执行 yarn global 的 pm2,无论是否安装 npm i -g pm2

danger

千万不要 yarn global add npm(如果 macOS 更新后或其他未知原因也可能导致出现以下问题),它会在 /usr/local/bin 中创建两个软链:npmnpx

将会导致无论用 nvm 怎么切换 node 或重新安装 npm,都会使 npm 的版本锁定在 yarn global 中 npm 的版本,如果 yarn global 中 npm 的版本过低,可能还会导致以下错误,没踩过坑的话会非常难以定位到该问题:

这时候也不要尝试升级 yarn global 中 npm 的版本,即使修改后版本兼容了,还有可能因为 yarn 中残留的 npm 版本问题导致以下错误:

最好通过 yarn global remove npm删除或者全局包不多的话可以彻底删除 global 文件夹:

$ rm -rf ~/.config/yarn/global

yarn help

显示帮助信息,效果如下:

Displays help information.

Options:

--cache-folder <path> specify a custom folder that must be used to store the yarn cache
--check-files install will verify file tree of packages for consistency
--cwd <cwd> working directory to use (default: /Users/sherryshen/code-other/docsite)
--disable-pnp disable the Plug'n'Play installation
......

yarn import

依据原 npm 安装后的node_modules目录生成一份yarn.lock文件

note

背景介绍:许多使用 npm shrinkwrapnode_modules 的项目无法轻易迁移到 Yarn,因为 yarn install 可能产生有很大差异的逻辑依赖关系树。不是所有树都可以用 Yarn 的 yarn.lock 表示,并且部分有效的树会在安装后自动按重复剔除。

yarn import 旨在使用在 node_modules 内找到的版本, 根据普通的 require.resolve() 解决规则生成一个 yarn.lock 文件以缓解这一重大问题。

yarn info

yarn info <package> [<field>]拉取包的信息。以yarn info react命令为例,在命令行输入:

yarn info react

打印的信息如下:

yarn info v1.19.2
warning package.json: No license field
{ name:
'react',
description:
'React is a JavaScript library for building user interfaces.',
'dist-tags':
{ latest:
'16.13.1',
next:
'0.0.0-d7382b6c4',
experimental:
'0.0.0-experimental-e5d06e34b',
canary:
'0.0.0-57333ca33',
unstable:
'0.0.0-da834083c' },
......

可以添加--json参数,例如:yarn info react --json,输出为JSON行格式;还可以添加版本参数 @[version] ,例如:yarn info react@16.13.1,以查看特定版本的信息

yarn list

yarn list 命令模仿 Unix 列目录命令的预期行为。 yarn list命令列出当前工作文件夹所有的依赖,通过参考所有包管理器的元信息文件,包括项目的依赖。实现效果如下:

yarn list v1.19.2
├─ @babel/code-frame@7.8.3
│ └─ @babel/highlight@^7.8.3
├─ @babel/compat-data@7.9.0
│ ├─ browserslist@^4.9.1
│ ├─ invariant@^2.2.4
│ └─ semver@^5.5.0
......

默认情况下,所有包和它们的依赖会被显示。 如果要限制依赖的深度,可以给 list 命令添加一个标志 --depth以控制所需的深度。注意:深度层级是从零索引的。

yarn list --depth=0

还可以根据 pattern 参数筛选出依赖列表:

yarn list --pattern gulp
yarn list --pattern "gulp|grunt"
yarn list --pattern "gulp|grunt" --depth=1

yarn login

此命令用来登录自己的 npm 账号。根据提示分别输入注册账号时填写的用户名和邮箱,不需要输入密码。之后就可以运行 yarn publish命令发布包,此时需要输入 npm 账号的密码才能成功发布。

yarn logout

退出登录 npm 账号

yarn publish

发布一个包到 npm 库

yarn publish

发布当前目录里 package.json 定义的包

yarn publish [tarball]

发布一个 .tgz gzip 压缩文件定义的包

yarn publish [folder]

发布包含在指定目录里的包。 <folder> package.json 应该指定包的细节

yarn publish --new-version <version>

使用version的值,跳过对新版本的询问

yarn publish --tag <tag>

<tag>参数为发布的包指定标签

yarn run

如果你已经在你的包里定义了 scripts,这个命令会运行指定的 script。例如:

yarn run test

还可以在脚本名称后放置要传递给脚本的额外参数:

yarn run test -o --watch

也可以在该命令中忽略 run,效果与yarn run test一样:

yarn test -o --watch
tip

npm 中除了start, install, test等官方命令外,自定义的命令前面都需要加 run,而 yarn 中自定义命令前的 run 可以省略。

yarn test

运行指定的test脚本,是 yarn run test 的快捷命令

yarn upgrade

该命令会根据在 package.json 文件中所指定的版本范围将依赖更新到其最新版本。也会重新生成 yarn.lock 文件

yarn upgrade [package | package@tag | package@version | @scope/] [--ignore-engines] [--pattern]
  • [package]:如果只写包的名字不指定版本,会自动升级到最新版本
  • [package@tag]: 指定包包含标签时,将升级到该标签的版本
  • [package@version]: 当指定包包含版本时,将升级到该版本
  • --ignore-engines: 此标志可用于跳过引擎检查。
yarn upgrade
yarn upgrade left-pad
yarn upgrade left-pad@^1.0.0
yarn upgrade left-pad grunt
yarn upgrade @angular

yarn upgrade --pattern <pattern> 将升级所有匹配此模式的包

yarn upgrade --pattern gulp
yarn upgrade left-pad --pattern "gulp|grunt"
yarn upgrade --latest --pattern "gulp-(match|newer)"
tip

当 major 为零的阶段(0.y.z),不会更 minor,只会更新 patch,因为该阶段相对不稳定。

  • 如:^0.6.6,表示更新版本范围 >=0.6.6 <0.7.0,可以是0.6.x
  • 如:^0.6,表示更新版本范围>=0.6.0 <0.7.0,可以是0.6.x

yarn [command] --verbose

详细日志模式,运行 yarn 命令时,增加参数--verbose,这在排查错误时很有帮助

yarn --cwd [path][command]

  • cwdcurrent working directory的缩写,中文是当前工作目录
  • 使用方式:yarn --cwd [path] [command],这个命令的含义是:通过--cwdpath参数,使得命令在path这个文件路径下执行
  • 注意:参数的顺序非常重要,不能改变,否则会出错
  • 适用于多层嵌套的项目

假设当前有一个多层嵌套的项目,结构如下:

/project
/layer1
/layer2

如果想在project/中指定yarn install命令在/layer1路径下执行,则该命令需要写为:

yarn --cwd layer1 install

如果--cwd [path]参数的使用顺序不对,则会报错,无法识别--cwd参数:

yarn install --cwd layer1
error: unknown option '--cwd'

yarn.lock

yarn.lock文件是在安装期间,由Yarn自动生成的,其中准确地存储着每个依赖的具体版本信息。当我们通过 yarn 增加、升级或者删除依赖时,它会自动更新 yarn.lock 文件。yarn.lock 文件应该由 yarn 来管理,不应该手动去更改,更不应该删除,且要提交到版本控制系统中,以免因为不同机器安装的包版本不一致引发问题。

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

"@babel/code-frame@7.8.3", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
dependencies:
"@babel/highlight" "^7.8.3"

@babel/code-frame为例,看看 yarn.lock 中会记录哪些信息:

  • 第一行"@babel/code-frame@7.8.3"包的 name 和语义化版本号,这些都来自package.json中的定义
  • version字段,记录的是一个确切的版本
  • resolved字段记录的是包的 URL 地址
  • dependencies字段记录的是当前包的依赖,即当前包在package.jsondependencies字段中的所有依赖

yarn dedupe

As you probably know, merges in yarn.lock are not always very clean, and you have to either solve the errors by hand, or re-apply the set of package updates that both branches did. And if you choose to solve it by hand, you’ll start to notice some package duplication here and there. For example, from React’s yarn.lock:

debug@^2.6.3:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
ms "2.0.0"

debug@^2.1.1, debug@^2.2.0:
version "2.6.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
dependencies:
ms "0.7.3"

In the above code, we have that some package of our project depends on debug@^2.6.3, but yarn installed debug@2.6.8. This is fine, because 2.6.8 can satisfy the requirement of ^2.6.3 and it is more modern.

In the next block we see that some package depends on debug@^2.1.1, and some other package depends on debug@^2.2.0. But in this case yarn installed debug@2.6.6, even when debug@2.6.8 (which is already installed!) could satisfy the dependencies as well. What we have here is package duplication: our project uses two different versions of debug when in fact we only need one to satisfy all requirements.

Thus, the aim of yarn dedupe is to deduplicate dependencies with overlapping ranges.

Dedupe all packages:

yarn dedupe

Dedupe all packages using a specific strategy:

yarn dedupe --strategy highest

Dedupe a specific package:

yarn dedupe lodash

Dedupe all packages with the @babel/* scope:

yarn dedupe '@babel/*'

Check for duplicates (can be used as a CI step):

yarn dedupe --check

For more options, see https://yarnpkg.com/cli/dedupe

.yarnrc

可以通过.yarnrc文件配置更多的 yarn 功能。 也可以用 yarn config 命令来配置这些选项。 yarn 会把 .yarnrc文件 merge 进文件树里。

note

优先级:.npmrc > yarn config > .yarnrc

模块扁平化

假设我项目的直接依赖(即当前项目的 dependencedevDependences 中的依赖,不包括依赖的依赖)中有 A,B,C 三个包,A 和 B 包同时依赖了相同版本范围的 D 包。那么这部分的依赖关系树是这样的:

├── A
│ └── D
├── B
│ └── D
├── C

如果按照这样的依赖关系树直接安装的话,D 模块会在 A 包和 B 包的 node_modules 中都安装,这样会导致模块冗余。

为了保证依赖关系树中没有大量重复模块,yarn 在安装时会做 dedupe(去重)操作,它会遍历所有节点,逐个将模块放在根节点下面,也就是当前项目的 node_modules 中。当发现有相同的模块时,会判断当前模块指定的版本范围是否交集,如果有,则只保留兼容版本,如果没有则在当前的包的 **node_modules** 下安装

所以上面的说的情况,最终安装完成是下面这样的,A,B,C,D 包都会安装在第一层 node_modules 下(在依赖的 D 版本兼容的情况下)。

├── A
├── B
├── C
├── D

如果 A 包和 B 包依赖的是不兼容的版本,假设 A 包依赖的是 D@1 版本的包,B 包依赖的是 D@2 版本。则最终安装的结果如下:

├── A
├── B
│ └── D@2
├── C
├── D@1

至于是 D 的哪个版本被安装在根目录的 node_modules 下,取决的是模块解析的顺序,先解析到的 D 的指定版本会被安装到根 node_modules,后解析到的 D 且不兼容已有版本时,会被安装到对应模块的 node_modules 下。

References

  1. Yarn official site
  2. Yarn 中文网
  3. yarn config
  4. npm-run-script
  5. De-duplicating yarn.lock
  6. yarn dedupe
  7. 关于 yarn 你需要知道的 by 前端小白的摸爬滚打