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.lockfile 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 versionis determined by thepackage.jsonfile. Theyarn.lockfile is only a lookup for which version and commit hash to install for the givensemver versionnumber.
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 Versionis not affected by what entries are present in the dependencies map for a module inyarn.lockfile.
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