This paper focuses on the following issues:

1. Semantic version

2. NPM dependency management policy

3. Yarn dependency management policy

4. Similarities and differences between NPM and YARN package management policies

ⅰ. Semantic version

Semantic version: Semantic Versioning or “semver”.

The standard version number must be in the format of X.Y.Z, where X, Y, and Z are non-negative integers and do not add zeros before digits. X is the major release number, Y is the minor release number, and Z is the revision number. Each element must be incremented numerically.

Where X: Major (major version), Y: minor (minor version), and Z: patch(patch version) can be interpreted as:

  • Major:Significant and incompatible changes have been made to the package.
  • Minor:New functionality has been added to the package and is backward compatible.
  • Patch:Fixes bugs in packages and is backward compatible.

The version number can be used with symbols such as >, >=, <, <=, =, ~, and ^ to indicate a version range. Note that by default, when a package is installed, the version number is ^ by default. NPM and YARN use semantic version for package management.

Version compatibility: If the ranges of two versions overlap, the two versions are compatible. For NPM and YARN, a compatible version is deduced to enable the normal use of both versions. For example, ^1.2.3 and 2.0.3 are incompatible, while ^1.2.3 and ^1.2.9 are compatible.

ⅱ. NPM package management strategy

Package management for NPM has gone through different stages. The major milestones came in versions V3 and V5.

Earlier versions of NPM used a nested strategy to install packages, which simply meant that packages dependent on package.json were installed in the project root directory, and packages used by those dependencies were installed in the node_modules folder of each dependency folder. This creates A dependency tree, which is neat, but it also leads to the fact that if A dependency package A is dependent on different dependencies, it will appear in the node_modules folder of each of them, which makes node_modules very large.

V3: To address these issues, the concept of flat dependencies was introduced in V3. Dependencies encountered during installation are placed first in node_modules in the root directory, and only in the dependent node_modules folder if version incompatibations are encountered. Such as: Json depends on A and B, A depends on C, and B depends on C. If the versions of C that A and B depend on are not compatible, then dependency C in A is first traversed during installation, and dependency C in A will be placed in node_modules in the root directory. C in B will be placed under node_modules in B. If A and B depend on compatible versions of C, then NPM will infer A compatible version of C and place it under node_modules in the root directory. This saves a lot of space if the dependent versions are compatible. However, there is still A problem, although this can partially solve the problem of dependency duplication, but there are still some problems, the main one is that if the installation of dependency A, B dependency C is not compatible, which dependency C of A, B will be placed in the root directory, it is uncertain. This will result in different dependency tree structures for different people to install, which will ultimately result in different bundles to be packaged.

V5: To address the uncertainty of installation dependencies, the use of package-lock.json was introduced in V5 to address this issue. If there is a package-lock.json file in the project, the package-lock.json file will be used to parse and install the specified version dependency packages when installing the project dependencies, rather than using package.json to parse and install the modules. Because package-lock specifies the version, location, and integrity hashes for each module and each of its dependencies, it creates the same installation each time. It doesn’t matter what device you use or if you install it in the future, it should give you the same results every time.

npm

It was not originally made according to the existing rules.

5.0 x version:

NPM install will download according to package-lock.json regardless of whether the package.json dependencies are updated. Someone made this issue about this installation strategy, and it evolved into a post-5.1.0 rule.

After 5.1.0:

When there is a new version of a dependency in package.json, NPM install ignores package-lock.json to download the new version of the dependency and update package-lock.json. In response to this installation strategy, there was an issue referencing the comments of NPM contributor Iarna, which came up with rules after version 5.4.2.

5.4.2 After Version:

If there is only one package.json file, running NPM install will generate a package-lock.json file from it, which is a snapshot of the install. It logs not only the versions of direct dependencies specified by package.json, but also the versions of indirect dependencies.

If the semver-range version of package.json is compatible with the package-lock.json version (package-lock.json version is within the version range specified in package.json), Even if there is a new version in package.json at this point, NPM install will still download according to package-lock.json.

If you manually modify the version ranges of package.json and they are incompatible with the package-lock.json version, Package-lock. json will be updated to a package.json compatible version when NPM install is executed.

ⅲ. Yarn Package management policy

Yarn features:

  • The parallel installation: no matternpmoryarnWhen you install a package, you perform a series of tasks.npmEach is executed by queuepackageThat is, it has to wait until nowpackageAfter the installation is complete, proceed with the subsequent installation. whileyarnSynchronizing all tasks improves performance.
  • Offline mode: If a package has been installed before, useyarnGet it from the cache between reinstalls, so you don’t have tonpmThen you can download it from the Internet.
  • Unified Installation version: To prevent pulling different versions,yarnThere is a lock file (lock file) records the version number of the module exactly installed. Every time I add a module,yarnIt creates (or updates)yarn.lockThis file. This ensures that the same module version is used each time the same project dependency is pulled.
  • Better semantics:yarnChanged a little bitnpmThe name of the command, for exampleyarn add/remove, thannpmThe originalinstall/uninstallBe clearer.

ⅳ. Similarities and differences between NPM and YARN package management policies

1. The deterministic algorithms of NPM5 + and YARN are different.

If you look at the package-lock.json file, you can see that package-lock.json can be viewed as a complete dependency tree of installed dependencies, completely marked with the position of each dependency after installation. So the package-lock.json file alone can determine the directory structure of the installed file.

If you view yarn.lock, you can find that all dependencies listed in yarn.lock are flat. It is impossible to determine whether each dependency resides in the root node_modules directory or its own node_modules directory. Therefore, package.json file is required to determine its location. For specific considerations, see [Reference 3].

2. Different flattening algorithms

Npm5 + package-lock.json lists the dependency order of all packages, with the first occurrence of the package name promoted to the top level, and subsequent repeats going into the node_modules of the dependent package. Cause incomplete flattening problem (there was this problem before, now do not know whether to solve it).

Lock of YARN is completely flat. Compatible versions with more references are stored in the root node_modules folder according to the algorithm, and those with fewer references are stored in the dependent node_modules folder.

Yarn.lock has only two levels of package dependencies and lists only directly dependent packages. If the dependent packages depend on other packages, they are listed in the same way, as follows: dumi-theme-moibile relies on lodash. Debounce:

If the version is compatible, the package is merged into one version and the highest version is used as follows. Many versions of Lodash are used in the project. Yarn selects the largest version that is compatible based on the compatibility policy:

An aside: The package management strategy has a direct impact on the final package size of tools such as Webpack, because webpack’s dependency graph lookup package will first be found in its own folder node_modules, and then in the upper node_modules, all the way up to the topmost node_moduels. An error is reported if it cannot be found. Therefore, flattening greatly reduces package size.

References:

1.semver.org/lang/zh-CN/

2. yarn.bootcss.com/docs/depend…

3. classic.yarnpkg.com/blog/2017/0…

4. docs.npmjs.com/cli/v6/conf…

5. Juejin. Cn/post / 684490…

6. segmentfault.com/a/119000003…

7. Juejin. Cn/post / 684490…

8. segmentfault.com/a/119000001…

9.zhuanlan.zhihu.com/p/377593512