preface

Have you ever encountered this scenario, after the project is pulled down, the yarn install is executed, but the yarn. Lock is prompted to change, I clearly did not do anything, why? Yarn.lock should not have diff, there must be something wrong with it. But Git Diff yarn.Lock found himself unable to read it either (my favorite dish 😭)

An 🌰

Restore my Case 😭 project originally had a dependency foo:

  • Package. jsonFoo @ ^ 1.0.1
  • The version in yarn.lock is1.0.1

Student A was responsible for the development of the library Foo. After the release, he upgraded the dependency to 1.1.0 in the project. However, when the code was submitted, only package.json was changed and yarn.lock was not updated

  • package.jsonFoo @ ^ 1.0.1 ` ` foo @ ^ 1.1.0
  • Yarn.lock hasn’t changed, or1.0.1

Yarn.lock file is changed every time you install a dependency. You must have forgotten to commit yarn.lock when you upgrade a dependency.

  • Let’s look at what version of foo library is available now. The latest version is1.1.2, as defined in package.json^ 1.1.0It’s two versions off. It’s not guaranteed online1.1.0, because every time the line, will go to find a match^ 1.1.0The latest version in this version range
  • So I took a look at the build log from the last time it went live, and what it downloaded was1.1.2
  • Yarn.lock is committed and the version is locked1.1.2

Then passed a day, pull group 😭

  • There were bugs in version 1.1.2, and 1.1.3 was released after fixing them

  • But in the project, because B locked the version in 1.1.2, locked the bug 😭

  • Student A: Why do YOU want to lock someone else’s version 😭

  • There are several todos in this case

    • Since yarn.lock was not submitted, I am not sure if student A passedyarn upgradeThe updated version still manually changes package.json, so — do not manually change the package.json updated version
    • After upgrading dependencies, be sure to commit package.json and yarn.lock at the same time

About yarn.lock

What does Yarn.lock do?

Lock the unique version!

  • Package. json defines the version range, such as^ 1.0.0
  • The yarn in the lockversionThe field is a unique version number, such as1.0.0

What does Yarn. lock look like?

There were pieces inside, and each piece looked something like this:

The core - js - compat @ ^ 3.0.0: The version "3.14.0" resolved "Https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz#b574dabf29184681d5b16357bd33d104df3d29a5" Integrity sha1 - tXTavykYRoHVsWNXvTPRBN89KaU = dependencies: browserslist "^ 4.16.6" semver 7.0.0 ""Copy the code

Identifier(s)

The first line of core-js-compat@^3.0.0 is the identifier of the dependency. The corresponding package name and version range in package.json are connected by @. I put (s) in the title here because it’s possible that multiple identifiers end up pointing to the same version (see ### Dependencies below for an example)

version

The second line version is the version actually installed. Usually it is one of the versions in the range. For example, in the previous line of identifier, the version range is ^3.0.0. Here, the actual installation is 3.14.0, which meets the requirements. But why do you say “usually”? Because there are exceptions, as you’ll see later in the ### Resolutions section.

resolved

The third line in Resolved is a link to download the package. The domain name part of this URL is related to the.npmrc configured in the project or your local NPM configured registry.

integrity

The fourth line, integrity, checks the integrity of the files that can be downloaded from the Resolved file. If diff appears, the file corresponding to the same download link has been modified.

dependencies

The fifth line dependencies is the package’s own dependencies. If you want to see which version of browserslist is installed, you can spell it Identifierbrowserslist@^4.16.6″ and search yarn.lock to find the corresponding block.

[email protected], browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.12.0, browserslist@^4.14.5, Browserslist @^4.16.0, browserslist@^4.16.6, browserslist@^4.3.6, browserslist@^4.6.2, browserslist@^4.6.4, Browserslist @ ^ 4.7.2, browserslist @ ^ 4.9.1: The version "4.16.6" resolved "Https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" integrity sha1-15ASd6WojlVO0wWxg+ybDAj2b6I= dependencies: Caniuse-lite "^1.0.30001219" colorette "^1.2.2" electron-to-chromium "^1.3.723" Escalade "^3.1.1" Noke-releases "^ 1.1.71"Copy the code

The example above has multiple Identifiers in the first line, which all end up pointing to version “4.16.6” in the second line. You can check that version 4.16.6 meets the version ranges in all of the above Identifiers: 4.16.6, ^4.0.0…

How is yarn.lock generated?

Yarn.lock is automatically generated, you should not manually modify it.

Dependency management

For example, our normal operations will automatically update package.json and yarn.lock

  • Add a dependency: yarn add

  • Upgrade dependency: YARN upgrade

More reference classic.yarnpkg.com/en/docs/man…

domineeringresolutions

If your project relies on foo,foo depends on bar@^1.0.0. Suppose bar now has two versions, 1.0.0 and 1.1.0. Unfortunately, bar was not backward compatible when 1.1.0 was released. As a result, foo and [email protected] cannot be used together. If you can wait:

  • Or etc.fooTo rely onbarLock into1.0.0And re-issued version
  • Or etc.barFix the compatibility problem and resend the version

What if you can’t wait? You already know that foo and [email protected] work. It would be nice if you could lock foo’s dependency on bar, but this is defined in foo’s packge.json, you can’t change node_modules/foo/package.json, can you? It’s not appropriate. Resolutions can solve your problem by defining it in your own project package.json:

/ / foo/bar/foo/bar/foo/bar/foo/barCopy the code

The key”foo/bar” represents foo’s direct dependence on bar, rewriting the version interval to 1.0.0. If foo is not directly dependent on bar (foo ->… -> bar), do I need to clear up all the links in the middle? Don’t bother!

/ / foo/**/bar: "1.0.0"}Copy the code

If you have many dependencies in your project that are directly/indirectly dependent on bar, each defined version range may be different, and you know that one version will make them all work without having to install multiple versions. You can also write the package name bar without declaring the prefix part. So wherever the bar depends on it will point to the version you declared.

/ / may all resolutions/resolutions come true.Copy the code

After running yarn install, search for bar@ in yarn.lock:

The bar @ ^ 1.0.0 [email protected] bar @ ^ 2.0.0: version "1.0.0"...Copy the code

As you can see, resolutions can violate the range limits, such as [email protected] ‘ ‘bar@^2.0.0 in the Identifiers in the above example.

How can problems be avoided?

Yarn. lock does not match package.json

scenario

Only change package.json and forget to commit yarn.lock

The problem

After yarn install is executed, yarn.lock is changed

How to solve

  • Solve the person who introduced the problem (PEACE & LOVE)

  • Confirm diff and commit yarn.lock after the change

    • Determine which dependencies generate diff and regression the related functions (the cost is a bit high and it is difficult to identify the impact if the dependencies are complex)

    • OR πŸ” will be the last available version (⚠️ may πŸ” live bug😭)

As you can see, it’s still tricky to solve the problem, and there’s a bit of gambling involved, so we’d better prevent it.

How to prevent

Even if the project is good now, shouldn’t we nip it in the bud?

  • Development of students &&CR check πŸ™πŸ»

  • Block build 😈 (there are several options)

    • NPM Ci is similar to NPM install, but if a package-lock-json mismatch is found during the dependency installation process, it will throw an error and exit without updating the lock file

    • Yarn install –frozen-lockfile is equivalent to NPM CI, but several problems were found during the test:

      • resolutionsIn the modified version, no error
      • Classic Yarn (version 1) removes dependencies in package.json without error (v2 fixes this problem, see github.com/yarnpkg/yar…
    • βœ…yarn install && git diff–exit-codeyarn.lock Run the install command to install dependencies and check whether the lock file has diff

      • Advantages: simple and rough && intuitive (there is no error in understanding the command or parameters resulting in inconsistent expectations)
      • Cons: Slow! Low efficiency! Because it will download all the dependencies that need to be updated, it should have stopped when it detected the need for an update (no good way to do it so far).

Delete the Lock file and reinstall the whole thing

scenario

When you update a dependency and the project doesn’t run, assume the dependency is the problem. – Did you try to delete yarn.lock + node_modules and reinstall it, if you’re lucky, it might be “problem solved” (it did, but it doesn’t seem to be completely resolved, since the project is running)

The problem

After yarn.lock is deleted, all locked versions are released. When yarn install is executed, the system searches for the latest version according to the version range defined in package.json. As a result, you can update dependencies that you didn’t expect, and unfortunately you can introduce bugs.

solution

We can create a separate dependency on empty-lock-lock:

  • Do nothing (an empty library), release the version1.0.0
  • To define apostinstallScript, throw directly wrong, release version1.0.1

If the installation depends on yarn add [email protected] –dev, the locked version in yarn.lock is 1.0.0. Then prepare a trap:

  • Manually change the version in package.json to a range^ 1.0.0
  • Manually change yarn.lock to the Identifier section[email protected]Also replaceEmpty - lock - lock @ ^ 1.0.0

After the modification is submitted, you can run yarn install to verify that yarn.lock does not have diff, which proves that our manually modified package.json and yarn.lock are still match. If you delete yarn.lock and run yarn install, you will find the latest version in the range ^1.0.0 defined in package.json, and you will find the version 1.0.1. Error: postinstall is not installed after download.

THE END

It is hoped that this article will shed some light on yarn.Lock’s mystery, and that the next time you see yarn.Lock produce diff, you will feel less confused and anxious. If you find any problems while reading, please be sure to correct them! Thank ❀️ thank the small partners in the team to discuss the problem && provide small miao (bamboo shoot) recruit. Gratitude Plus ❀ ️ ❀ ️ ❀ ️

The resources

  • Robertcooper. Me/post/how – ya…

Further reading

  • Package. Json defined in a variety of dependent on πŸ”— classic.yarnpkg.com/en/docs/pac…

Welcome to “ByteFE”

Resume delivery email: [email protected]