Details neglected in NPM dependency management

Time:2021-1-28

The third66An original article ~
This article starts from the blog of Zhengcai cloud front-end team: [details ignored in NPM dependency management]
](https://www.zoo.team/article/…
Details neglected in NPM dependency management

preface

When it comes to NPM, the first thing you think of is NPM install, but the node generated after NPM install_ Have you ever observed modules? package- lock.json Do you know the role of documents? Apart from dependencies and devdependencies, what is the role of other dependencies? Next, this article will share some experience with you for the details you may ignore in NPM.

NPM installation mechanism

A and B depend on C at the same time. Where will C be installed? What’s the difference between the same version and different versions of C? package.json Does the sequence of packages have any effect on installation? We may not have noticed these problems at ordinary times. Let’s study them together today.

A and B depend on C at the same time. Where will this package be installed?

If there are two packages a and B, and both packages depend on the package C, NPM 2 will recursively install the packages a and B and their dependent packages to the node in turn_ Modules. After the implementation, we will see./node_modulesThis directory only contains these two subdirectories:

node_modules/ 
├─┬ A 
│ ├── C 
├─┬ B 
│ └── C 

If NPM 3 is used for installation,./node_modulesThe directory under will contain three subdirectories:

node_modules/ 
├─┬ A 
├─┬ B 
├─┬ C 

Why is there such a difference? This starts from the way NPM works

The difference of NPM 2 and NPM 3 module installation mechanism

Although the latest version of NPM is NPM 6, the change from NPM 2 to NPM 3 achieves directory flattening, which is quite different from other versions. So let’s look at the differences between the two versions.

When NPM 2 installs dependency packages, it uses a simple recursive installation method. implementnpm installAfter that, NPM determines the first layer of dependencies according to the packages specified in the dependencies and devdependencies attributes, and NPM 2 recursively installs each package to the node of the sub dependencies according to the sub dependencies of the first layer of dependencies_ Modules until the child dependency is no longer dependent on other modules. After the implementation, we will see./node_modulesWe are included in this directory package.json All the dependent packages in the file, and the sub dependent packages of these dependent packages are installed in their own nodes_ In modules, form a dependency tree similar to the following:

Details neglected in NPM dependency management

Such a directory has obvious advantages

1) the hierarchical structure is very obvious, which can be clearly displayed in the node of the first layer_ In modules, you can see the subdirectories of all the packages we installed;

2) when you know the name and version number of the package you need, you can copy and paste the corresponding file to the node_ Modules, and then change it manually package.json Configuration in the system;

3) if you want to delete a package, simply delete it package.json File, and then delete the node_ The directory of the package in modules;

However, this hierarchical structure also has obvious defects. When my three packages a, B and C have the same dependency D, the execution ofnpm installAfter that, D will be downloaded three times, and as our project becomes more and more complex, node_ The dependency tree in modules will become more and more complex, and there will be more and more packages like D, resulting in a lot of redundancy; in Windows system, even the file path will be too long because the directory level is too deep, triggering the error that the file path cannot exceed 280 characters;

In order to solve the above problems, the node of NPM 3_ The modules directory has been changed to a more flat hierarchical structure, and the dependencies and their dependencies are tiled on the node as far as possible_ Modules folder.

How does NPM 3 handle different versions of the same dependency?

NPM 3 will traverse all the nodes and put the modules in the node one by one_ In the first layer of modules, if duplicate modules are found, they will be discarded. If some dependent versions are incompatible, the NPM 2 method will continue to be used, and the previous one will be placed in node_ In the modules directory, the following ones are placed in the dependency tree. For example: A, B, depends on D (V 0.0.1), C depends on D (V 0.0.2): A, B, D (V 0.0.1)

Details neglected in NPM dependency management

But NPM 3 will bring a new problem: due to the implementation ofnpm installAt the same time, according to thepackage.jsonIn the figure above, if the order of C is in front of a and B, node_ The modules tree will change and the following situation will appear:

Details neglected in NPM dependency management

It can be seen that NPM 3 does not completely solve the problem of redundancy, and even brings new problems.

Why does package appear- lock.json What about it?

Why package- lock.json What about the documents? We have to start with this package.json It’s the document.

package.json The inadequacies of

After NPM install is executed, a node is generated_ The modules tree, in an ideal case, would like to package.json Always generate exactly the same node_ Modules tree. In some cases, it is. But in most cases, NPM can’t do that. There are two reasons

1) Some dependencies may have released new versions since they were last installed. For example, when package a was first installed in the team, it was version 1.0.5, package.json The configuration item in isA: '^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 package.json In this case, the version of a after the second person NPM install is 1.0.8, which may cause bugs due to different versions;

2) To solve the problem in 1), some partners may want to fix the version number of a toA: '1.0.5'Isn’t that ok? However, such an approach does not solve the problem. For example, when the first person downloads a dependency, it is version 2.1.3, but when the second person downloads it, it has been upgraded to version 2.2.5, and the node generated at this time_ The modules tree is still not exactly the same, the fixed version is only fixed from its own version, and the dependent version cannot be fixed.

in the light of package.json Solutions to the problems

In order to solve the above problems and NPM 3 problems, a package will be automatically generated after NPM 5.0 and NPM install- lock.json When there is a package in the package- lock.json When NPM install is executed, if package.json And package- lock.json According to the package- lock.json If it is not compatible, it will be downloaded according to the package.json Update package- lock.json Package is guaranteed- lock.json Version compatibility in package.json .

package- lock.json Structure of documents

package- lock.json Name, version and package.json Like name and version in, it describes the name and version of the current package. Dependencies is an object, which is the same as node_ The package structure in modules corresponds one by one. The key of the object is the name of the package, and the value is some description information of the packagePackage lock JSON official documentThe main structure is as follows:

  • version: package version, that is, the package is currently installed innode_modulesVersion in
  • resolved: package specific installation source
  • integrity: packagehashValue to verify whether the installed software package has been changed and is invalid
  • requiresDependency corresponding to child dependency, and dependency corresponding to child dependencypackage.jsonindependenciesThe dependencies of are the same
  • dependenciesStructure and outer layerdependenciesThe structure is the same, and the storage is installed in the child dependencynode_modulesDependency packages in

It’s important to note that not all child dependencies have child dependenciesdependenciesProperty, only child dependencies and dependencies that are currently installed in the root directorynode_modulesThis property is available only after the dependency conflicts in.

package- lock.json The role of documents

  • In team development, ensure that the dependent versions installed by each team member are consistent, and determine a unique node_ Modules tree;
  • node_ The modules directory itself will not be submitted to the code base, but the package- lock.json It can be submitted to the code base. If the developer wants to trace back to the directory status of a certain day, he just needs to package.json And package- lock.json These two files can be returned to that day.
  • Due to package- lock.json And node_ The dependency nesting in modules is exactly the same, so we can have a clearer understanding of the tree structure and its changes.
  • During installation, NPM compares nodes_ Modules, existing packages, and packages- lock.json Compare, if repeated, skip the installation, thus optimizing the installation process.

The difference of dependency and usage scenarios

NPM currently supports the following types of dependency package management, including

  • dependencies
  • devDependencies
  • Optional dependencies optional dependency packages
  • Peer dependencies
  • Bundled dependencies

Let’s take a look at the differences between these dependencies and their respective application scenarios

dependencies

Dependencies are dependencies that must be used in both development and production environments. They are the most commonly used dependency package management objects, such as react, loadsh, Axios, etcnpm install XXXThe downloaded packages will be installed in the dependencies object by default, and can also be usednpm install XXX --saveDownload the packages in dependencies;

Details neglected in NPM dependency management

devDependencies

Devdependencies refer to the dependencies that can be used in the development environment, such as eslint, debug, etcnpm install packageName --save-devAll downloaded packages will be in the devdependences object;

Details neglected in NPM dependency management

The biggest difference between dependencies and devdependencies is that when the package runs, thenpm installAll dependencies will be installed by default when usingnpm install --productionIf it is a node service project, you can use this method to install and package the service at runtime to reduce the package size.

optionalDependencies

Optionaldependencies refer to optional dependencies. When you want some dependencies to run normally or NPM to continue to run even if the download fails or is not found, you can put these dependencies in the optionaldependencies object, but optionaldependencies will override dependencies So don’t write one package into two objects at the same time.

Optional dependencies is like a protection mechanism for our code. If a package exists, it will follow the logic of existence. If it does not exist, it will follow the logic of nonexistence.

try { 
  var axios = require('axios') 
  var fooVersion = require('axios/package.json').version 
} catch (er) { 
  foo = null 
} 
// .. then later in your program .. 
if (foo) { 
  foo.doFooThings() 
} 

peerDependencies

Peerdependencies is used to specify the version of the package that your current plug-in compatible host must install. What does this mean? For example: our common react component library [email protected] Ofpackage.jsonThe configuration in is as follows:

"peerDependencies": { 
  "react": ">=16.9.0", 
  "react-dom": ">=16.9.0" 
 }, 

Suppose we create a project called project, in which we use the [email protected] This plug-in, at this time our project must first installReact >= 16.9.0andReact-dom >= 16.9.0Version of.

In NPM 2, when we download [email protected] The dependencies specified in peerdependencies are updated with the [email protected] So we don’t need to install it in the package.json The file specifies the dependencies in peerdependencies, but in NPM 3, peerdependencies will not be forced to install In this case, you need to manually enter the package.json Add dependency manually in the file;

bundledDependencies

This dependency can also be recorded as bundledependencies. Different from other dependencies, it is not an object of a key value pair, but an array in which the string of package name is contained

{ 
  "name": "project", 
  "version": "1.0.0", 
  "bundleDependencies": [ 
    "axios",  
    "lodash" 
  ] 
} 

When NPM pack is used to package, the above example will generate a project-1.0.0.tgz file. After bundledependencies is used, Axios and lodash will be put into the package together, and then someone will use themnpm install project-1.0.0.tgzWhen the package is downloaded, the dependencies Axios and lodash are also installed. It should be noted that after installation, the information of Axios and lodash packages is in dependencies, and the version information is not included.

"bundleDependencies": [ 
    "axios", 
    "lodash" 
  ], 
  "dependencies": { 
    "axios": "*", 
    "lodash": "*" 
  }, 

If we use the normal NPM publish to publish, this attribute will not take effect, so it is less used in daily situations.

summary

This paper introduces NPM 2, NPM 3, package- lock.json As well as the differences and use scenarios of several kinds of dependence, I hope to make you know more about NPM. If there are any unclear points or deficiencies, you are welcome to leave a message in the comment area.

reference

package.json Official documents

Package lock JSON official document

NPM document summary

npm-pack

invite to one ‘s side men of wisdom and valor

Zooteam, a young, passionate and creative front-end team, belongs to the product R & D Department of Zhengcai cloud. It is located in the picturesque Hangzhou. The team now has more than 50 front-end partners, with an average age of 27 years old. Nearly 30% of them are full stack engineers and young storm group. The members are not only the “old” soldiers from Alibaba and Netease, but also the new recruits from Zhejiang University, China University of science and technology, Hangzhou power and other universities. In addition to the daily business docking, the team also carried out technical exploration and actual combat in the direction of material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, promoted and implemented a series of internal technical products, and continued to explore the new boundary of front-end technology system.

If you want to change what you have been tossed about, you want to start tossing things; if you want to change what you have been told, you need more ideas, but you can’t break the situation; if you want to change, you have the ability to achieve that result, but you don’t need you; if you want to change what you want to achieve, you need a team to support, but you don’t have the position to lead people; if you want to change the established rhythm, it will be If you want to change the original understanding is good, but there is always a layer of window paper fuzzy If you believe in the power of belief, believe that ordinary people can achieve extraordinary things, believe that you can meet a better self. If you want to participate in the process of business take-off and personally promote the growth of a front-end team with in-depth business understanding, perfect technology system, technology creating value and spillover influence, I think we should have a chat. Any time, waiting for you to write something, send it[email protected]

Details neglected in NPM dependency management

Recommended Today

Practice of query operation of database table (Experiment 3)

Following the previous two experiments, this experiment is to master the use of select statements for various query operations: single table query, multi table connection and query, nested query, set query, to consolidate the database query operation.Now follow Xiaobian to practice together!Based on the data table (student, course, SC, teacher, TC) created and inserted in […]