Most front-end developers are familiar with NPM and YARN and understand some of their basic uses. In this article, we will review the conventions related to the NPM version and then discuss the differences between NPM, YARN, and PNPM.

1. Semantic version

1.1 Version Settings

Json file, you can see the various dependencies of the current project, and the introduction of semantic versions is an important part of NPM dependency management. Let’s first look at the recommended version number management:

  • Version 1.0.0 when first released
  • Backward compatibility bug fixed after version 1.0.x
  • Backward compatible new features are released in version 1.x.0
  • Destructive changes to upgrade version 2.0.0

We can simply call a major release bit, b minor release bit, and C patch release bit in a version A.B.C

For more information

Version 1.2 Symbol

The ^ symbol locks the first non-zero version bit. For example, ^1.0.0 locks major 1.x and does not match 2.x, while ^0.1.0 locks 0.1.x and does not match 0.2.x, and so on.

The ~ symbol locks the sub-version bits, for example ~1.0.0 matches in the 1.0.x range and does not match 1.1.0 or later.

For more information

2. Iteration of NPM itself and existing problems

2.1 Too deep hierarchy and a large number of duplicate files

NPM implements node_modules after NPM I before nPM3, and installs dependencies at each level in a strictly nested manner as shown below:

Node_modules └ ─ a ├ ─ index. Js ├ ─ package. The json └ ─ node_modules └ ─ b ├ ─ index. The js ├ ─ package. The json └ ─ node_modules └ ─ c ├ ─ Index. Js └ ─ package. Json...Copy the code

Predictably, problems arise when dependencies become complex:

  1. Too deep file hierarchy, resulting in too long file path, A-B-C-d…
  2. Dependencies are installed repeatedly. Because of nested dependencies of each module, if a project has 10 modules that depend on the same module A, module A will be installed 10 times
  3. Inefficient use of local caching (data)
  4. Inefficient file storage, when there are 10 projects on the computer, and each project depends on the same module, the computer will store 10 related files.

2.2 Efficiency improvement brought by flat file structure

NPM, starting with nPM3, gradually introduced flat dependency structures and package-lock.json (NPM5) to solve some of the problems mentioned above, as shown below:

Node_modules ├ ─ a | ├ ─ index. Js | └ ─ package. The json ├ ─ b | ├ ─ index. The js | └ ─ package. The json └ ─ c ├ ─ index. The js └ ─ package. The json . // The default dependency is installed to the top node_modules, When encountering different versions of the same dependency // for example, the top node_modules already exists [email protected] // now detects that module B depends on [email protected], [email protected] will be installed to node_modules in module B's directoryCopy the code

(The rule for modules to find dependencies is to start from node_modules in the current folder and work up to the parent node_modules until the dependencies are found.)

  1. The design of flat structure almost solves the problem of too deep hierarchy and dependence on repeated installation
  2. The introduction of package-lock.json also addresses dependency consistency issues
  3. The new cache design also improves the cache efficiency

However, we can also see and experience some new or unresolved hidden dangers:

  1. Unauthorized access to undeclared modules. If module A depends on module B, and module B depends on c, the current dependency structure makes module A accessible to module C
  2. Inefficient file storage, continuing the previous problem, when there are 10 projects on the computer, and each project depends on the same module, the computer will store 10 related files

3. Yarn and PnP mode

Yarn started to solve the problems of NPM from the very beginning, introducing dependency cache, flat dependency structure and yarn.lock design to ensure efficient reuse of files and the certainty of dependency structure, but there are still dependency illegal access problems after NPM improvement. However, PnP mode proposed by YARN has a new breakthrough in improving file storage efficiency.

The PnP pattern sets out to reduce excessive file IO overhead when dependent on installation. After the dependencies in the node_modules folder are downloaded from the source address to the local cache, the most important parts include decompressing the dependencies and copying them to the node_modules directory of the current project. According to analysis by the YARN team, the time consumed for copying dependencies can account for 70% of the total dependency installation time. So they designed a way to save dependency installation time by managing and mapping dependency locations through.np. Js files instead of copying dependency packages (node_modules are not generated in the project folder, dependency files are retrieved by.np. Js maps).

4. What did PNPM do

PNPM is a package manager similar to NPM/YARN, but unlike them, the author designs a theoretically more complete dependency structure and efficient file reuse to solve the problems that NPM/YARN is not intended to solve or is not complete enough.

4.1 Nesting + flat + pnpm-lock.yaml

Open the project node_modules folder installed via PNPM and you’ll find almost all dependencies declared in the current package.json, while the “real” module files exist in node_modules/.pnpm, Flat storage by folder in the form of module name @ version number (eliminates dependency on repeated installation).

In this way, the problem of cross-declaration access in the project is very well avoided, because the current project node_modules can only be accessed by declared dependencies.

The pnpm-lock.yaml file, like yarn.lock and package-lock.json, can provide a stable version of each dependency for the project.

4.2 Hard links and more efficient reuse

Similar to the PnP mode of YARN, files stored in node_modules/. PNPM are hard links to actual PNPM cache files to improve file storage efficiency and reduce file I/O overhead. In this way, space waste caused by multiple files brought by multiple projects is avoided.

PNPM also makes additional use of a content-addressed file system to store dependent files. When two versions of module A dependencies exist but only one file of the earlier versions is different, PNPM adds only one new file to maximize file storage efficiency. For more information

4.3 Test Data

Next, let’s look at a comparison of the official figures. In most cases, PNPM can increase speeds nearly twice as fast as NPM/YARN:

5. Talk about implicit dependencies

Then, let’s talk about implicit dependencies. An implicit dependency is an illegal access to a module that is not declared to the current project. First of all, it is important to avoid introducing implicit dependencies. Let’s look at the reasons for this:

After the project relies on is flat design, when the project relies on the module b, and module b dependent module c cases, we can direct access to the module in the project a c, but predictable, assuming module in version b in the process of iteration updated module c version destructive changes brought module (c), Or when module C is removed, project A will be in trouble.

6. Summary

Compared with NPM/YARN, PNPM provides a more secure dependency structure, higher file storage, and faster installation experience. In actual development, for new projects, I think you can consider introducing experience; For older projects, you can also try migrating to PNPM if the previous dependencies introduce rigor.

Finally, post the official introduction document

And more reading: Deep Thoughts on modern package managers — Why do I now recommend PNPM over NPM/YARN? Node_modules Dilemma Front-end engineers should know about YARN Which do you choose, NPM or YARN?

The above.