New features in NPM 7.0

NPM 7.0 belatedly supports Monorepo

Horizontal comparison of Monorepo solutions

More and more monorepo solutions are being used in large-scale projects. The most common monorepo solutions are the workspaces features of Lerna and YARN.

  • The advantage of LERna is the implementation of the “unified workflow” aspect. The disadvantage is that dependency promotion has limitations and cannot solve the problem of dependency explosion (Lerna directly compares the version of dependency with a string, promotion is required only when the version is identical, semver convention does not work here)

  • Yarn can declare packages in package.json in the workspaces field, and Yarn manages packages as monorepo. Compared with LERNA, YARN focuses on dependency management, including dependencies of packages and dependencies on third parties. Yarn analyzes the version of Dependencies using semver convention, and installs dependencies faster and occupies less space.

  • Most Monorepos use both Lerna and declare workspaces in package.json. This way, whether your package manager is NPM or YARN, you can take advantage of Monorepo;

NPM/YARN dependency evolution history

npm2: npm3: NPM 3 traverses all nodes and places modules one by one in the first layer of node_modules. When it finds duplicate modules, it discards them. If it encounters incompatible dependencies, it continues to use NPM 2 and places the previous modules in the node_modules directory. The latter ones are placed in the dependency tree. For example 🌰 : A, B, D(v 0.0.1), C (v 0.0.2):But NPM 3 introduces a new problem: due to executionnpm installWhen, according topackage.jsonThe node_modules tree will change if C is in front of A and B.

The downsides of package.json

When NPM install executes, it generates a node_modules tree. Ideally, you want to always generate exactly the same node_modules tree for the same package.json. In some cases, it is. But in most cases, NPM fails to do this. There are two reasons: 1) Some dependencies may have been released in new versions since the last installation. For example, package A was installed as version 1.0.5 by the first person on the team, and the configuration item in package.json is A: ‘^1.0.5’; When the second person in the team pulled down the code, the version of package A had been upgraded to 1.0.8. According to semver-range version specification in package.json, the version of package A after the second person installed by NPM was 1.0.8. May cause bugs due to different versions of dependencies; 2) For the problem in 1), some friends might fix the version number of A as A: ‘1.0.5’. For example, one of the dependencies of A was version 2.1.3 when the first person downloaded it, but the second person downloaded it and upgraded it to version 2.2.5, the generated node_modules tree is still not the same, and the fixed version is only fixed to its own version. Dependent versions cannot be fixed.

A workaround for package.json deficiencies

In order to solve the above problems and NPM 3 problems, after NPM 5.0, NPM install will automatically generate a package-lock.json file, when the package contains package-lock.json file, When NPM install is executed, if package.json and package-lock.json versions are compatible, it will be downloaded according to package-lock.json versions. If not, the package-lock.json version will be updated according to the package.json version. It is guaranteed that the package-lock.json version is compatible with package.json.

Lock file structure and function

Composition: docs.npmjs.com/cli/v6/conf…

  • version: Package version, that is, the package is currently installed innode_modulesThe version in
  • resolved: Indicates the installation source of the package
  • integrity: packagehashValue to verify whether the installed software package has been changed or has become invalid
  • requires: corresponds to the dependencies of child dependencies, and of child dependenciespackage.json 中 dependenciesHas the same dependencies
  • dependenciesStructural and outerdependenciesThe structure is the same as the storage installed in the child dependenciesnode_modulesDependency packages in

Note that not all child dependencies have a dependencies property. They only have dependencies that conflict with those currently installed in node_modules in the root directory. Function:

  • In team development, ensure that the dependency versions installed by each team member are consistent, and determine a unique node_modules tree;
  • The node_modules directory itself is not committed to the code base, but package-lock.json can be, and if the developer wants to go back to the directory status of a particular day, Just roll back the package.json and package-lock.json files to that date.
  • Since the nesting of dependencies in package-lock.json and node_modules are exactly the same, you can get a clearer picture of the structure of the tree and how it changes.
  • NPM optimizes the installation process by comparing existing packages for node_modules with package-lock.json and skipping the installation if they are duplicated.

Type of dependency

NPM currently supports the following types of dependency package management

  • dependencies

    • Dependencies are dependencies that must be used in both development and production environments
  • devDependencies

    • DevDependencies are dependencies that can be used in either a development environment or a test environment
  • OptionalDependencies Optional dependency package

    • PtionalDependencies are optionalDependencies that you place in the optionalDependencies object if you want to keep your project running even if the download fails or the NPM fails to find. However, optionalDependencies overwrites dependencies of the same name, so don’t write the same package to both objects.
  • PeerDependencies are equally dependent

    • PeerDependencies specifies the version of the package that your current plug-in compatible host must install
  • BundledDependencies Bundles dependency packages

    • This dependency is also called bundleDependencies. Unlike the other dependencies, it is not an object of key-value pairs. Instead, it is an array of strings containing package names, such as:
{" name ":" the project ", "version" : "1.0.0", "bundleDependencies" : [" axios ", "lodash"]}Copy the code
  • This example generates a project-1.0.0. TGZ file when packed with NPM pack dependencies. After bundledDependencies is added to the package, the Axios and Lodash dependencies are added to the packageNPM install project - 1.0.0. TGZThe Axios and Lodash dependencies are also installed when the package is downloaded. Note that the information about Axios and Lodash packages is in Dependencies and does not include version information.
"bundleDependencies": [ 
    "axios", 
    "lodash" 
  ], 
  "dependencies": { 
    "axios": "*", 
    "lodash": "*" 
  },
Copy the code
  • This property would not work if we used regular NPM publish, so it is rarely used in everyday situations.

yarn install

Classic.yarnpkg.com/en/docs/cli…

Reference: Github. Blog /2020-10-13-… Github.com/npm/rfcs/bl… Docs.npmjs.com/specifying-… Classic.yarnpkg.com/en/docs/cli… Classic.yarnpkg.com/zh-Hans/doc… Docs.npmjs.com/cli/v6/conf…