In this paper, the author compares the differences between the current mainstream package management tools NPM, YARN, PNPM, and puts forward appropriate recommendations.

NPM

NPM is one of the main reasons node.js is so successful. The NPM team has done a lot of work to ensure that NPM remains backward compatible and consistent across different environments.

NPM is designed around the idea of Semantic version control (Semver). Here is an excerpt from their website:

Given a version number: the major version number. Minor version number Patch version number: You need to add the corresponding version number in the following three cases:

  • Major version number: When an API changes and is incompatible with a previous version
  • Secondary version number: when functionality is added but backward compatible
  • Patch version number: when backwards-compatible defects are fixed

NPM uses a file called package.json in which the user can save all the dependencies in the project by using the NPM install –save command.

For example, running NPM install –save lodash adds the following lines to the package.json file.

"dependencies": {
    "lodash": "^ 4.17.4"
}
Copy the code

Note that there is a ^ character before the version number Lodash. This character tells NPM to install any major version equal to 4. So if I run NPM now to install, NPM will install the latest version of LoDash with major version 4, probably [email protected] (@ is the specified version used by the NPM convention to determine the package name). You can be in here to view all the supported character: docs.npmjs.com/misc/semver.

In theory, a change in the secondary version number should not affect backward compatibility. Therefore, installing the latest version of the dependency library should work and introduce important bug and security fixes since version 4.17.4.

But, on the other hand, even if different developers use the same package.json file, they may install different versions of the same library on their own machines, potentially leading to hard-to-debug errors and “on my computer…” In the case.

Most NPM libraries are heavily dependent on other NPM libraries, which leads to nested dependencies and increases the chances of failing to match the corresponding version.

Although you can turn off the default behavior of using ^ before version numbers by using the NPM config set save-exact true command, this only affects top-level dependencies. Because each dependent library has its own package.json file, and their own dependencies may be preceded by ^ symbols, there is no guarantee that the contents of nested dependencies can be provided through package.json files.

To address this, NPM provides the shrinkwrap command. This command generates an npm-shrinkwrap. Json file that records the exact version for all libraries and for all nested dependencies.

However, even with the nPm-shrinkwrap. Json file, NPM locks only the version of the library, not the contents of the library. Even though NPM can now prevent users from publishing the same version of the library multiple times, the NPM administrator still has the power to force updates to certain libraries.

Here’s a quote from the self-shrinkwrap document:

If you want to lock down specific bytes in a package, for example to ensure proper redeployment or build, then you should check dependencies in source control or have some other mechanism for validating content other than the version.

NPM 2 installs all the dependencies that each package depends on. If we have A project that depends on project A, project A depends on project B, and project B depends on project C, the dependency tree will look like this:

node_modules
- package-A
-- node_modules
--- package-B
----- node_modules
------ package-C
-------- some-really-really-really-long-file-name-in-package-c.js
Copy the code

This could be a very long structure. This is no more than a minor annoyance for UNIx-based operating systems, but it’s a major nuisance for Windows because there are many programs that can’t handle file pathnames longer than 260 characters.

NPM 3 uses flat dependency trees to solve this problem, so our three project structures now look like this:

node_modules
- package-A
- package-B
- package-C
-- some-file-name-in-package-c.js
Copy the code

In this way, A long file path name changed from./node_modules/ package-a /node_modules/ package-b /node-modules/some-file-name-in-package-c.js to /node_module S/some – file – name – in – package – SAN Antonio s.

You can read more about how NPM 3 dependency resolution works here.

The downside of this approach is that NPM must first traverse all project dependencies before deciding how to generate flat node_modules directory structures. NPM must build a complete dependency tree for all modules used, which is a time-consuming operation and a significant reason for the slow installation of NPM.

Since I didn’t understand the NPM changes in detail, I assumed that every time I ran the NPM install command, NPM would have to download everything from the Internet.

However, I was wrong. NPM has a local cache, which holds the compressed package of every version that has been downloaded. You can run the NPM cache ls command to view the contents of the local cache. Local caching is designed to help reduce installation time.

All in all, NPM is a mature, stable, and interesting package manager.

Yarn

Yarn was launched in October 2016 and quickly gained 24,000 stars on Github. NPM only has 12,000 stars. The project is maintained by a number of senior developers including Sebastian McKenzie (babel.js) and Yehuda Katz (ember.js, Rust, Bundler, etc.).

From what I can gather, Yarn’s primary goal at the beginning was to solve the problem of NPM installation uncertainty described in the previous section due to semantic versioning. While NPM Shrinkwrap can be used to implement predictable dependency trees, it is not the default option and is up to all developers to know and enable this option.

Yarn takes a different approach. Each YARN installation generates a yarn.lock file similar to npm-shrinkwrap. Json, and it is created by default. In addition to the general information, the yarn.lock file contains a checksum of what is being installed to ensure that the version of the library being used is the same.

Because YARN is the new, redesigned NPM client, it allows developers to parallelize all the necessary operations, and some other improvements have been added, which has resulted in a significant increase in speed and reduced overall setup time. I suspect that the speed increase is the main reason for YARN’s popularity.

Like NPM, YARN uses local caching. Unlike NPM, YARN does not require an Internet connection to install local cache dependencies and provides offline mode. This feature was proposed in the NPM project in 2012, but never implemented.

Yarn also provides some other improvements, such as the nice fact that it allows you to merge licenses for all packages used in your project.

One interesting thing is that the attitude of the YARN documentation began to change towards NPM as the YARN project became popular.

The initial YARN bulletin describes the installation of YARN as follows:

* The easiest way to get started is to run:

npm install -g yarn 
yarn*
Copy the code

The yarn installation page now says:

Note: Installation through NPM is generally not recommended. NPM installations are nondeterministic, packages are not signed, and NPM does no integrity checking beyond basic SHA1 hashing, which poses a security risk for installing system programs.

For these reasons, it is strongly recommended that you install YARN using the installation method that is most appropriate for your operating system.

At this rate, we wouldn’t be surprised if YARN announced their own Registry, allowing developers to slowly phase out NPM.

It seems that thanks to YARN, NPM has finally realized that they need to pay more attention to some of the issues that have been so strongly requested. When I was reviewing the “offline” feature that I strongly requested earlier, I noticed that this requirement was being actively fixed.

pnpm

As I mentioned, in PNPM author Zoltan Kochan’s post “Why PNPM?” After that, I learned about PNPM.

I won’t go into too many details (since this post is so old), but you can check out my original post to find out more and also join the discussion on Twitter.

but

I want to point out that PNPM runs very fast, even faster than NPM and YARN.

Why so fast? Because it takes an ingenious approach of using hard and symbolic links to avoid copying all locally cached source files, this is one of YARN’s biggest performance weaknesses.

Using links is not easy and brings up a number of issues to consider.

As Sebastian pointed out on Twitter, he originally intended to use symbolic links in YARN, but abandoned it for other reasons.

At the same time, PNPM can be used by many people, as there are over 2,000 stars on Github.

In addition, as of March 2017, it inherits all the benefits of YARN, including offline mode and deterministic installation.

conclusion

I think the yarn and PNPM developers have done an amazing job. I personally like deterministic installation because I like control and I don’t like surprises.

Whatever the outcome of this competition, I am grateful to YARN for lighting a fire under NPM and providing an alternative.

I’m sure YARN is a safer choice, but PNPM may be a better choice for some test cases. For example, it can be useful in small to medium-sized teams that are running a lot of integration tests and want to install dependencies as quickly as possible.

In the end, I think NPM still provides a very useful solution that supports a large number of test cases. Most developers can still do just fine with the original NPM client.

More RN references

Pros and cons of React – Native technology

React Native open source projects to learn

React Native Combat Lesson 1

React Native Rn