323

In npm, there's a ci command for installing the project with a clean state. In the documentation, it is claimed that:

It can be significantly faster than a regular npm install by skipping certain user-oriented features. It is also more strict than a regular install, which can help catch errors or inconsistencies caused by the incrementally-installed local environments of most npm users.

What is the closest equivalent of the npm ci command in yarn world? Maybe the answer is that we don't need this in yarn because its architecture is such that we don't need a special mode. Maybe the answer is to use a bunch of configuration settings. However, I'm failing to find a single complete answer to this question and I believe it would be valuable to have it.

Pang
  • 9,564
  • 146
  • 81
  • 122
shabunc
  • 23,119
  • 19
  • 77
  • 102

6 Answers6

515

I believe it's as simple as that:

yarn install --frozen-lockfile
Pang
  • 9,564
  • 146
  • 81
  • 122
fab67
  • 5,192
  • 1
  • 8
  • 5
142

Unfortunately, because of the way yarn module resolution works, just doing yarn install --frozen-lockfile is sometimes not enough. You can still be left with transitive deps that are invalid.

To truly get the same behavior as npm ci you must do:

rm -rf node_modules && yarn install --frozen-lockfile
VanTanev
  • 1,678
  • 1
  • 10
  • 7
  • 2
    indeed! I wonder why this answer is not the most voted one :( Sometimes by accident before optimizations we do a full copy of the project files for the Dockerfile (sadly some 'guides' to copy paste from ... ) This causes a few headaches over time... The docs to explain the npm CI make it more obvious: https://docs.npmjs.com/cli/v7/commands/npm-ci – Kostas Kapetanakis Feb 26 '21 at 17:10
  • 16
    @KostasKapetanakis Perhaps because people are using transient build agents that have no knowledge of previous runs? – Zhaph - Ben Duguid Jul 15 '21 at 08:32
  • 9
    if you as running that on CI, it probably is already installing on a fresh folder. Having a node_modules already present would mean bad practice. – wkrueger Jun 22 '22 at 22:48
79

For newer versions of yarn you should use:

yarn install --immutable --immutable-cache --check-cache

As stated in the official Yarn docs:

If the --check-cache option is set [...] This is recommended as part of your CI workflow if you're both following the Zero-Installs model and accepting PRs from third-parties, as they'd otherwise have the ability to alter the checked-in packages before submitting them.

Kutyel
  • 8,575
  • 3
  • 30
  • 61
27

building off of @Crafty_Shadow's recommendation, I make it a bit more integrated.

package.json

  ...
  "scripts": {
    ...
    "preci": "rm -fr node_modules",
    "ci": "yarn install --frozen-lockfile"
  },
  ...
Mike LP
  • 671
  • 8
  • 13
  • That doesn't work for me, it seems that the package.json "ci" definition is not visible by npm in my case, dunno why though.. (note, I do not have package-lock.json, I just want to use `npm ci` in a generic way for a yarn project). – rantoniuk Feb 16 '21 at 09:10
  • 2
    When using just *yarn* you will not have a `package-lock.json` file. That is created when using *npm* to install. You probably need to do `npm run ci` – Mike LP May 20 '21 at 14:40
  • 3
    @warden That's because `npm ci` is a native command `ci`. You'll have to use `npm run ci`, as pointed out in the previous comment. – adi518 Jul 12 '21 at 15:51
0

I would like to take a moment to try and give more insights on --frozen-lockfile, --pure-lockfile, and --no-lockfile

  1. --frozen-lockfile

    a. It actually means don't generate a lockfile and fail if an update is needed.

    b. The accepted answers did not answer what if the user still wants to install the dependencies from the existing yarn.lock file. The command is fine if you want to check if a minor or patch version in any dependency has been updated and you have allowed them to use ^,~,>, <, =, >= or <= or in the version value. If there is any update, the command will eventually fail else it will make a node_module directory with dependencies.

    c. This is dicey if you do this in Dockerfile and CD may fail on the cloud if at all any update is required..

  2. --pure-lockfile

    a. This means don't generate a lockfile, but still there are activities happening when yarn sees some range conflicts.

    b. Suppose you have a package X with version 3.2.1 in package.json file and you create a yarn.lock file. This is fine for a happy path.

    c. Now after a month you update the dependency to ^3.2.1, [in real life this will happen gradually] and run yarn install --pure-lockfile, you will see that your package.json file has changed. Your behavior of the code may break due to this and anyways while committing the code to the CI you will notice this in DIFF.

    d. Why this happened? --pure-lockfile forbids yarn to create a yarn.lock file, correct?

    e. When a pure lockfile is used, the lockfile is not written if no changes have occurred since the last time it was generated. This means that if the installed package versions and their dependencies have not changed, the lockfile is not rewritten, and the existing lockfile is considered to be up to date.

    f. If a range isn't in the lockfile (and in your example ^3.2.1 isn't in your lockfile - 3.2.1 is) then Yarn will resolve it again without considering the other ranges that are part of your lockfile (such as 3.2.1). Said differently, the ranges must match exactly to be considered.

    g. This behavior is in contrast to other lockfile implementations that always write the lockfile, even if there are no changes to the installed packages or their dependencies. The advantage of a pure lockfile is that it reduces unnecessary changes to the project's files, which can help reduce conflicts and make it easier to track changes to the project over time.

    h. So make sure while you commit code, the package.json and yarn.lock are in sync before the code goes to CI/CD and may affect containerization.

  3. --no-lockfile

    a. It actually means don't read or generate a lockfile. This command is used to install packages without generating a lockfile.

    b. This is helpful when you want rapid prototyping where you are quickly testing out different packages or ideas, and don't need the overhead of a lockfile. This can help speed up the development process by avoiding the time required to generate and update the lockfile. Never recommended when deploying to production.

Ankur Soni
  • 5,725
  • 5
  • 50
  • 81
-1

Windows cmd:

rd /s /q node_modules && yarn install --frozen-lockfile
General Grievance
  • 4,555
  • 31
  • 31
  • 45
puxiao
  • 1
  • 3