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/…
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_modules
This directory only contains these two subdirectories:
node_modules/
├─┬ A
│ ├── C
├─┬ B
│ └── C
If NPM 3 is used for installation,./node_modules
The 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 install
After 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_modules
We 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:
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 install
After 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)
But NPM 3 will bring a new problem: due to the implementation ofnpm install
At the same time, according to thepackage.json
In 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:
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_modules
Version inresolved
: package specific installation sourceintegrity
: packagehash
Value to verify whether the installed software package has been changed and is invalidrequires
Dependency corresponding to child dependency, and dependency corresponding to child dependencypackage.json
independencies
The dependencies of are the samedependencies
Structure and outer layerdependencies
The structure is the same, and the storage is installed in the child dependencynode_modules
Dependency packages in
It’s important to note that not all child dependencies have child dependenciesdependencies
Property, only child dependencies and dependencies that are currently installed in the root directorynode_modules
This 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 XXX
The downloaded packages will be installed in the dependencies object by default, and can also be usednpm install XXX --save
Download the packages in dependencies;
devDependencies
Devdependencies refer to the dependencies that can be used in the development environment, such as eslint, debug, etcnpm install packageName --save-dev
All downloaded packages will be in the devdependences object;
The biggest difference between dependencies and devdependencies is that when the package runs, thenpm install
All dependencies will be installed by default when usingnpm install --production
If 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.0
andReact-dom >= 16.9.0
Version 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.tgz
When 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
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]