Mastering yarn.lock file
If your default package manager is yarn, you should have noticed the yarn.lock
file created / updated every time you change your dependencies. But do you really know what this file is used for ? Which problem it solves ? How to use it efficiently ?
Through this article, it'll try to present you this file and answer some frequently asked questions about it.
#Semantic versioning
First of all, to understand how yarn.lock works, you should know what semantic versioning is. The official npm website gives a pretty good definition of it :
To keep the JavaScript ecosystem healthy, reliable, and secure, every time you make significant updates to an npm package you own, we recommend publishing a new version of the package with an updated version number in the package.json file that follows the semantic versioning spec.
You can find the semantic versions in your package.json file. Next to the version
entry (it corresponds to the version of your own project) and next to each of your dependencies / devDependencies / peerDependencies (it indicates which version - or range of versions - you're using).
#Incrementation
A semantic version is composed by 3 numbers. eg: 5.2.1
. Each number correponds to a type of change and should be incremented (or not) based on it. Let's focus on each part.
The last number (1 in our example) corresponds to a PATCH release; i.e. backward compatible bug fixes. It's incremented when a new version of the library is published and it contains only some small bugfixes that shouldn't create any regression. The second number (2 in our example) corresponds to a MINOR release; i.e. backward compatible new features. It's incremented when a new version of the library is published and it contains some new features that are backward compatible. It can also includes some bug fixes. The important part here is that it's backward compatible. And finally, the first number (5 in our example) stands for a MAJOR release; i.e. changes that break backward compatibility. When this number is changed, it means that some fixes / features will (or may) break your use of the library.
Please also note that the first version of a published library should be 1.0.0.
#Specify the versions of your dependencies
As mentionned earlier, in your package.json file, you have to specify the version (or range of versions) of each of your dependencies. I'll present you here the most common ways of specifying it.
When you add a new library to your project through yarn add
command, the default version of the added library will be prefixed by a ^
(eg: react: ^16.4.1
). This sign means that you accept every new update of the library as long as it's only a PATCH or a MINOR release.
You can also restrict it a little bit more by replacing the ^
by a ~
(eg: react: ~16.4.1
) so that it accepts only MINOR releases.
For those 2 signs, everytime you'll do a new install, it'll download the most recent version of the library as long as it matches the semantic version you've set.
You can even more restrict it by not prefixing it at all: it will only accept the specified version (eg: react: 16.4.1
).
You can find some other examples on the semantic version calculator and even test them.
#The problem it solves
Let's take the following example:
- we are still using the react library with its corresponding version set to
^16.4.1
- currently the latest version published of react is
16.4.1
- the yarn.lock file doesn't exist
Everytime a user will do yarn install
to install all the dependencies, it will download the 16.4.1 version of react. Which is ok !
But now, let's say that the React team published a new version 16.5.0. When a user will do a new yarn install
, it will download this 16.5.0 version of react (because it matches the semantic versioning we've set). Normally, it should be ok as it's only a MINOR release so it shouldn't break our code...
But what if, for any reason, this update contains an unwanted breaking change ? For example if the react library had a bug in 16.4.1 and you did a trick to fix it and now the new 16.5.0 fixes it but your own fix creates a bug ?
How can we ensure that every user of our project is using the same exact version of react ?
Here comes the yarn.lock file !
Thanks to this file, each time you'll add or update one of your dependency, the corresponding hash will be saved. And so when you'll run a new yarn install
, it'll download the version of the library based on this hash ! Even if a new version of the library is published, as long as you haven't updated it on purpose, it'll always use the version of the yarn.lock.
Please note that it also saves the corresponding semantic version that you've set to the library in your package.json file.
#FAQ
#Should I version my yarn.lock file ?
Of course yes ! 🙂 The yarn.lock will be your source of truth. It will ensure that everybody use the same version of all your dependencies. If it's not versioned, it's exactly as if it doesn't exist...
#What happens if I manually change the version of one of my dependencies ?
If you do that (for example to match a new range of version), when you'll do a yarn install
, it'll update your yarn.lock file to propagate this change. And if there is a new version of the library matching your new semantic version, it'll also contain the new corresponding hash.
#I just ran a yarn install
and my yarn.lock file has been updated. Is it normal ?
Not really... It means that, at some point, someone has changed the package.json file (by adding / updating / removing a library) and forgot to push the new version of the yarn.lock file... So you need to find who did this and check with him if the change on the package.json file has been done on purpose or not and update the yarn.lock file accordingly.
#What should I do in case of conflict on yarn.lock file ?
Usually, a conflict on this file goes along with a conflict on package.json. First of all, you should fix the conflict of the package.json file manually and then, since Yarn 1.0.0, running a yarn install
should fix the conflict of the yarn.lock. You should see something like this in your console:
info Merge conflict detected in yarn.lock and successfully merged.
Please note that you shouldn't delete the file and regenerate one (because it may install some new versions of a lot of dependencies) or even fix it manually.
If you liked this article, please share it on Twitter.
Victor Gosse
@VictorGosseI work at Attineos since 2015 as a front-end developer. This blog is mine and I'll be very happy to discuss about it with you in DM on Twitter.