Reading yarn.lock
yarn.lock
is the name of the lockfile used by yarn to track dependencies in a project.
Although the file is autogenerated and not meant to be read by a human, the reality is that more often than not you'll
need to understand how the file is structured, to be able to resolve conflicts, provide feedback in Pull Requests, etc.
Working with yarn.lock
can be daunting, specially if you have past experience with its NPM counterpart,
package-lock.json
.
However, you'll find yarn.lock
has a much more simpler structure. yarn.lock
is a collection of "dependency
resolution blocks". Each one of the blocks have a format like:
clipboard@2.0.4, clipboard@^2.0.0, clipboard@^2.0.1:
version "2.0.4"
resolved "https://registry..."
integrity sha512-Vw26VSLRpJfBofiVaFb....
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
Let's go line by line:
clipboard@2.0.4, clipboard@^2.0.0, clipboard@^2.0.1:
That is the header of the block. Is a list of one or more version specifications separated by a comma. They can be fixed
versions (clipboard@2.0.4
) or ranges (clipboard@^2.0.1
). It means that this block applies to any package in your
dependency tree that depends on one of those versions.
version "2.0.4"
This means that all the dependencies specified in the header (clipboard@2.0.4, clipboard@^2.0.0, clipboard@^2.0.1
)
will be resolved with this specific version of the package, clipboard@2.0.4
in this case.
This has two implications that are worth mentioning:
-
No matter where in your dependency tree appears
clipboard@^2.0.1
, it will always be resolved withclipboard@2.0.4
. This is not the case when using NPM. -
No matter how other packages specify a dependency on clipboard: if it is not one of the 3 versions specified in the header of the block, they will not get
clipboard@2.0.4
, they will get something else.
resolved "https://registry..."
integrity sha512-Vw26VSLRpJfBofiVaFb....
These two lines specify where the package will be downloaded from, and a checksum that will be used to validate that the package has not been tampered with.
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
These are the dependencies of this package. Note that yarn doesn't make a difference between dependencies
,
devDependencies
, optionalDependencies
... That information is already encoded in the package.json
file of the
package.
Note that, technically, there is no need to specify the dependencies here. yarn could extract the same information from
package.json
. I believe those dependencies are here to speed up some lookup process, and more importantly, to help
humans navigate yarn.lock
.
The important part is that for each dependency listed here, there will be another block in yarn.lock
specifying how
that dependency is resolved. But be careful, the format is slightly different: here it is good-listener "^1.2.2"
, but
the block defining that package will have good-listener@^1.2.2
in its title.
As you can see, the content of yarn.lock
is not really complicated. Manually inspecting it can give us a lot of
information about our tree. I have used yarn.lock
for:
-
Find out who is bringing some dependency. For example, who is importing
acorn@6.1.1
? Openyarn.lock
, find the relevant block (tip: it will haveacorn
in the header, andversion: "6.1.1"
), and then search for each version range specified in the header (remember to change the syntax, i.e. add the@
) -
Find duplicated packages: the best way is to search for part of the URL, for example search for
https://registry.yarnpkg.com/loglevelnext/
. For each occurrence of that URL, it means that a different version of the package will be present in your tree. -
Continuing with duplicated packages: once you have find all the blocks that install a dependency, you can check their headers to find the versions ranges. It is very useful to find out why a super old version of a package is still present on your tree.