I use yarn to install packages directly from the companies' GitLab:
yarn add git+ssh://<user>@<host>:<repo>
For first-level dependencies, I use yarn --pure-lockfile
to reconstruct my node_modules
according to the yarn.lock
.
However, for second level dependencies yarn seems to always install the latest version.
So let's say I depend on A
which is tested with a specific version of B
. In A's package.json
I don't specify the version, but it is contained in the yarn.lock
.
When I now install package A
yarn will get the latest version of B
despite the entry in A/yarn.lock
I know that I might resolve this by passing a specific version in A/package.json
(at least I think).
But is there an option to tell yarn to look at the yarn.lock
of dependencies?
TLDR:
When you install dependencies in your application, only your own yarn.lock file is respected. Lockfiles within your dependencies will be ignored. Reference
Let's get some things cleared first:
--pure-lockfile
is same as normal yarn install except that it won't generate a yarn.lock
file or update one if present.yarn.lock
by default for resolving dependencies while installing unless supplied with --no-lockfile
. So, there is no need to tell it to read from yarn.lock
. What is yarn.lock
used for?
yarn.lock
is used for resolving what version
should be fetched
given the semver version
of a module in package.json
. It is not used to determine what semver version
should a module be resolved to. That is simply not its use-case.
As mentioned in yarn DOCS: In order to get consistent installs across machines, Yarn needs more information than the dependencies you configure in your package json.. Yarn needs to store exactly which versions of each dependency were installed.
To do this Yarn uses a
yarn.lock
file in the root of your project.
So, for resolving semver version
of a dependency, yarn always depends on package.json
. For a given semver version
, yarn checks the yarn.lock
file to see what version
should it fetch. This is what makes yarn Deterministic (Same tecknique is used by npm
which uses npm-shrinkwrap.json
).
Example: Semver Versions like ^1.2.4
can resolve to any version number which is >= 1.2.3 and < 2.0.0
. Without yarn, npm would install 1.2.4
in one machine but 1.9.9
in some other machine, depending on the latest version present at the time of install. This is the problem that yarn solves using yarn.lock
.
The
semver version
is determined by thepackage.json
file. Theyarn.lock
file is only a lookup for which version and commit hash to install for the givensemver version
number.
How does yarn resolve version of a module given its semver version?
Suppose currently our yarn.lock file looks like this:
[email protected]:
version "2.9.6"
resolved "https://<...>/bluebird-2.9.6.tgz#1fc3a6b1685267dc121b5ec89b32ce069d81ab7d"
bluebird@^2.9.30:
version "2.11.0"
resolved "https://<...>/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
...
[email protected]:
version "5.1.0"
resolved "https://<...>/moduleA-5.1.0.tgz#ce97130858add59d616ee80675383b0c127290a0"
dependencies:
bluebird "^1.0.0"
bluebird: "^2.9.30"
, yarn looks for an entry bluebird@^2.9.30
in the lockfile. It is present and hence is resolved to version=2.11.0
.bluebird: "^2.9.0"
, yarn looks for an entry bluebird@^2.9.0
in the lockfile. It is not present. Suppose the latest stable version which satisfies semver criteria is 2.13.0
, then yarn adds an entry for bluebird@^2.9.0
, resolved to 2.13.0
. While resolving version for a given semver version
of bluebird, it does not matter what entry is present for bluebird in moduleA's dependencies in the lockfile.
Semver Version
is not affected by what entries are present in the dependencies map for a module inyarn.lock
file.
So, if package.json has bluebird: ""
, yarn looks for an entry bluebird@
in the lockfile but is unable to find it. Hence, it resolves bluebird: ""
to the latest version, suppose 3.5.0
. Now, yarn will add an entry for bluebird@
resolved to 3.5.0
.
bluebird@:
version "3.5.0"
resolved "https://<...>/bluebird-3.5.0.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
Form now on whenever yarn encounters {bluebird: ""}
, it will find an entry for bluebird@
in the lockfile and hence will always resolve it to 3.5.0
.
Solution to your problem
To resolve B: ""
to version say 1.0.0
, you need to have an entry for B@
in yarn.lock
resolved to 1.0.0
. Once, yarn.lock
has an entry for B@
, all the successive installs will always fetch version 1.0.0
for B=""
.
Following are the steps you need to take to accomplish the same:
Approach 1 (Recommended)
If you want B to resolve to latest version:
B:""
in A's package.json yarn install
. This will add an entry for B@
resolved to latest version.yarn.lock
file.yarn install
will get the same version.Approach 2
If you want B to have an older version: (Highly Not Recommended)
B: 1.0.0
in A's package.json. yarn install
. This will add an entry [email protected]
in the lockfile.B@
alongside [email protected]
in yarn.lock. B@, [email protected]: ...
""
in A's package.json.yarn.lock
file. yarn install
will get the B's version as 1.0.0
.This approach is highly dangerous as you can break something easily. Your yarn.lock file should always be managed by yarn.
Approach 3 (Recommended)
If you want B to stay at 1.0.0
1.0.0
in A's package.json.yarn install
. This will add an entry [email protected]
in the lockfile.yarn install
will get the B's version as 1.0.0
.Edit: Using the yarn.lock file present in the dependencies
If you check this doc:, they have clearly mentioned that yarn will use only the top level yarn.lock file and ignore the lock files present in the dependencies.
There is currently no way of locking down second level dependencies using yarn.lock present in them. I don’t see any need for it. In fact the creators of yarn explain here why that is the case. The reasons being:
Also, as in your use-case, if A has a dependency B which works only with version 1.0.0
, A’s package.json should have version mentioned for B as 1.0.0
and not “”. You can always fix your top-level yarn.lock
to add an entry for B@
resolved to 1.0.0
but it is not recommended to manually fix a yarn.lock file as I have mentioned above.
Hope this helped! Please ping me in the comments for any doubts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With