在使用 Yarn 管理项目的依赖时,会在项目根目录生成一个 yarn.lock 文件。这个文件的内容格式,大体如下:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
一些简单的解释:
- 最开始的两行,是一些注释内容。这里 Yarn 使用的还是 v1 版本,v2 版本的 Yarn 依然在规划中,目前的进度可以查看这里。根据规划,v2 版本的 yarn.lock 将会成为 YAML 的一个子集,在格式上也会和 v1 有些许不同(比如 #5892 提到的去除 registry 的改动);
ansi-styles@^3.2.0
是在项目某个依赖的 package.json 中使用到的依赖。需要注意的是,这里^3.2.0
是一个依赖的允许范围,而不是某个固定的版本号(具体允许的范围参考 semver 的定义)。只规定一个版本范围而不是某个固定的版本号,这在 Node.js 中是非常常见的,但也容易因此造成问题(如,各个环境具体安装的版本号不一致,导致运行结果有差异);- Yarn 为了解决上面一条提到的问题,通过 yarn.lock 文件锁死了版本号。上面例子中,
version "3.2.1"
表示的就是,最终 Yarn 使用 3.2.1 这个版本。如果有多个依赖最终使用相同的一个版本,Yarn 会将这些内容合并成一条显示,并用,
进行分割; resolved
这个字段,表示当前的依赖应该从哪个位置进行下载。在 v1 中,这个地址是一个包含 registry 的完整地址;在 v2 版本中,前面的 registry 会被隐去,方便开发者进行 registry 的切换(参考 #5892 的讨论);integrity
这个字段,表示当前下载的包对应的 Hash 值。这个值会被用于检查开发者下载的包是否符合预期,如果下载的结果 Hash 值不同,Yarn 会报错并停止安装的步骤;dependencies
这个字段,表示当前的包还有哪些需要的依赖,这部分的字段和该包内 package.json 中写的dependencies
字段内容是一一对应的。
如果开发某些工具,需要解析 yarn.lock 文件的内容,可以使用 Yarn 官方提供的 @yarnpkg/lockfile
工具(npm 地址见这里,GitHub 地址在这里)。
@yarnpkg/lockfile
提供了两个 API,分别是 parse
(负责读)和 stringify
(负责写)。用起来也很简单,参考官方给出的例子:
const fs = require('fs');
const lockfile = require('@yarnpkg/lockfile');
// or (es6)
import fs from 'fs';
import * as lockfile from '@yarnpkg/lockfile';
let file = fs.readFileSync('yarn.lock', 'utf8');
let json = lockfile.parse(file);
console.log(json);
let fileAgain = lockfile.stringify(json);
console.log(fileAgain);
经过 @yarnpkg/lockfile
解析后的 Yarn.lock,返回的对象结构如下:
{
"type": "success",
"object": {
}
}
这里,type
字段有三种可能的结果,分别是(代码见这里):
success
:表示正常的 yarn.lock 文件;merge
:表示存在 Git Merge Conflict 且自动 merge 的 yarn.lock 文件;conflict
:表示存在 Git Merge Conflict 且无法自动 merge 的 yarn.lock 文件。
而 object
对象中存储的内容是 yarn.lock 文件真正的解析结果(其中 conflict
情况下输出空对象,见这里)。
还是以最开始的 yarn.lock 内容为例,经过 @yarnpkg/lockfile
解析之后,object
中的对象,结构如下:
{
"ansi-styles@^3.2.0": {
"version": "3.2.1",
"resolved": "xxx",
"integrity": "sha512-xxx",
"dependencies": {
"color-convert": "^1.9.0"
}
},
"ansi-styles@^3.2.1": {
"version": "3.2.1",
"resolved": "xxx",
"integrity": "sha512-xxx",
"dependencies": {
"color-convert": "^1.9.0"
}
}
}
可以看到基本上和之前 yarn.lock 文件给出的数据是一一对应的。如果将这个对象传递给 stringify
函数,会得到一个 yarn.lock 文件的字符串,可以用于更新 yarn.lock 文件的内容。其中,这里无论给的对象是 {type:"success",object:{}}
还是仅 object
字段内的对象,都是可以正确生成 yarn.lock 文件的。