This is the 66th article of NPM dependency management. If you want to get more original articles, please follow us on our official account
preface
Node_modules NPM install node_modules node_modules Package-lock. json is a package-lock.json file. Besides dependencies and devDependencies, what do other dependencies do? Next, this article will share some lessons you might have missed in NPM.
NPM installation mechanism
Both A and B depend on C. Where will the package C be installed? What is the difference between installing the same VERSION of C and a different version? Does the sequence of packages in package.json have any effect on installation? These problems usually we may not pay attention to, today we come together to study it.
Both A and B depend on C. Where will the package be installed?
If there are two packages, A and B, both of which depend on C, NPM 2 will recursively install A and B and their dependencies into node_modules. After executing, we’ll see that the./node_modules layer only contains these two subdirectories:
├─┬ A │ ├── C │ ├─┬ B │ ├─ CCopy the code
If NPM 3 is used for installation, the directory under./node_modules will contain three subdirectories:
Node_modules / ├─┬ A ├─┬ B ├─┬ CCopy the code
Why the difference? This starts with the way NPM works:
Differences between NPM 2 and NPM 3 module installation mechanisms
Although the latest version of NPM is currently NPM 6, the changes from NPM 2 to NPM 3 have implemented directory leveling, which is quite different from other versions. So, let’s look specifically at the differences between the two versions.
NPM 2 uses a simple recursive installation approach when installing dependency packages. After NPM install is implemented, NPM recurses to node_modules and installs the packages specified in the dependencies and devDependencies properties. Until the child dependencies no longer depend on other modules. After executing, we can see that the./node_modules layer contains all dependencies from our package.json file, and their children are installed in their own node_modules, forming a dependency tree similar to the following:
Such a directory has obvious benefits:
1) The hierarchy is very obvious, you can see the subdirectories of all the packages we installed in node_modules in the first layer;
2) When you know the package name and version number you need, you can copy and paste the corresponding file into node_modules, and then manually change the configuration in package.json.
3) If you want to delete a package, simply delete a line in package.json and then delete the package directory in node_modules.
However, such A hierarchy also has obvious defects. When there is the same dependency D in my packages A, B and C, D will be downloaded three times after NPM install is executed. As our project becomes more and more complex, the dependency tree in node_modules will also become more and more complex. There will also be more and more packages like D, causing a lot of redundancy; In Windows, the file path is too long because the directory level is too deep, triggering an error that the file path cannot exceed 280 characters.
To address these issues, NPM 3’s node_modules directory has been changed to a more flattened hierarchy, with dependencies and dependent dependencies tiled under node_modules as much as possible.
What does NPM 3 do with different versions of the same dependency?
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, D(v 0.0.2):
NPM 3, however, introduces A new problem: since NPM install is executed in package.json, the node_modules tree changes if C comes before A and B, and the following situation occurs:
Thus, NPM 3 does not completely solve the problem of redundancy, and may even introduce new problems.
Why package-lock.json?
Why is there a package-lock.json file? We’ll start with the package.json file.
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 people may think that the version number of A is fixed 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.
Package-lock. json file structure
Package-lock. json file name, version, package.json file name, version, package.json This object corresponds to the package structure in node_modules. The key of the object is the name of the package and the value is the description of the package. According to the package-lock-json official documentation, the main structure is as follows:
version
: Package version, that is, the package is currently installed innode_modules
The version inresolved
: Indicates the installation source of the packageintegrity
: packagehash
Value to verify whether the installed software package has been changed or has become invalidrequires
: corresponds to the dependencies of child dependencies, and of child dependenciespackage.json
中dependencies
Has the same dependenciesdependencies
Structural and outerdependencies
The structure is the same as the storage installed in the child dependenciesnode_modules
Dependency 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.
Package-lock. json file
- 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.
Dependency differences and usage scenarios
NPM currently supports the following types of dependency package management
- dependencies
- devDependencies
- OptionalDependencies Optional dependency package
- PeerDependencies are equally dependent
- BundledDependencies Bundles dependency packages
Let’s take a look at the differences between these dependencies and their application scenarios:
dependencies
Dependencies include React, Loadsh, Axios, etc. NPM install XXX installs packages in the Dependencies object by default. You can also use NPM install XXX –save to download packages in dependencies.
devDependencies
NPM install packageName –save-dev devDependencies refers to dependencies that can be used in the development environment, such as esLint, debug, etc.
The difference between dependencies and devDependencies is that NPM install installs all dependencies by default. If NPM install — Production is used, only the dependencies in Dependencies will be installed. If it is a Node service project, it can be used for service runtime installation and packaging to reduce package size.
optionalDependencies
OptionalDependencies are optionalDependencies that 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.
OptionalDependencies are like a protection mechanism for our code: if packages exist, they exist, and if they don’t, they don’t exist.
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()
}
Copy the code
peerDependencies
PeerDependencies specifies the version of the package that your current plugin-compatible host must install. For example 🌰 : the package.json configuration of our common React component library [email protected] is as follows:
"peerDependencies": {
"react": "> = 16.9.0"."react-dom": "> = 16.9.0"
},
Copy the code
Suppose we create a project called project, in which we will use the [email protected] plugin, our project will have to install the React >= 16.9.0 and react-dom >= 16.9.0 versions.
In NPM 2, when we download [email protected], the dependencies specified in peerDependencies are forcibly installed along with [email protected], So we don’t need to specify the dependencies in peerDependencies in the package.json file of the host project. However, in NPM 3, the package specified in peerDependencies is no longer forced to be installed. At this point, you need to manually add dependencies to the package.json file;
bundledDependencies
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": "project"."version": "1.0.0"."bundleDependencies": [
"axios"."lodash"]}Copy the code
BundledDependencies: < span style = “color: RGB (51, 51, 51); line-height: 20px; font-size: 14px! Important; word-break: break-all;” When someone later downloads the package using NPM install project-1.0.0. TGZ, the Axios and Lodash dependencies will also be installed. 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.
conclusion
This article introduces NPM 2, NPM 3, package-lock.json and the differences and usage scenarios of several dependencies. We hope to make you understand more about NPM.
reference
Package. json Official document
Package-lock-json Official document
Summary of NPM documentation
npm-pack
Recommended reading
Dark mode adaptation guide
How to develop cross terminal applications based on Electron
, recruiting
ZooTeam, a young passionate and creative front-end team, belongs to the PRODUCT R&D department of ZooTeam, based in picturesque Hangzhou. The team now has more than 50 front-end partners, with an average age of 27, and nearly 30% of them are full-stack engineers, no problem in the youth storm group. The members consist of “old” soldiers from Alibaba and netease, as well as fresh graduates from Zhejiang University, University of Science and Technology of China, Hangzhou Electric And other universities. In addition to daily business docking, the team also carried out technical exploration and practice in 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’s been bothering you, you want to start bothering you. If you want to change, you’ve been told you need more ideas, but you don’t have a solution. If you want change, you have the power to make it happen, but you don’t need it. If you want to change what you want to accomplish, you need a team to support you, but you don’t have the position to lead people. If you want to change the pace, it will be “5 years and 3 years of experience”; If you want to change the original savvy is good, but there is always a layer of fuzzy window… If you believe in the power of believing, believing that ordinary people can achieve extraordinary things, believing that you can meet a better version of yourself. If you want to be a part of the process of growing a front end team with deep business understanding, sound technology systems, technology value creation, and impact spillover as your business takes off, I think we should talk. Any time, waiting for you to write something and send it to [email protected]