Modular development is becoming more popular on the front end, and node and NPM make it easy to download the dependency modules needed to manage your project. Package. json is used to describe the project and the module information on which the project depends.

Package-lock. json is a package-lock.json package.

package.json

Management package

As you all know, package.json is used to describe the project and the module information on which the project depends. “, which helps us manage dependency packages in our projects, keeps us out of dependency hell.

With NPM management, package.json is automatically generated using a few simple commands, and installation package dependencies are managed by package.json, and we hardly have to worry about them.

Semantic versioning

First let’s look at the definition of the version number of the dependent package

The version number consists of three parts: major.minor.patch, major version number. Minor version Number. Patch version number.

For example, 1.2.3, Major 1, Minor 2, patch 3.

  • The patchThe change in represents a bug fix that does not break anything.
  • minorChanges to indicate new functionality that does not break any content.
  • Major versionRepresents a major change that breaks compatibility. If users are not comfortable with major version changes, the content will not work.

How do I specify the version of the installation dependencies

I’m sure you’ve all experienced that when we install some dependency packages, the version number will be preceded by the symbol ^ or ~. What do these two symbols stand for?

~ will match the most recent minor version dependencies. For example, ~1.2.3 will match all 1.2.x versions, but not 1.3.0

^ will match the latest large version dependencies, for example ^1.2.3 will match all 1.x.x packages, including 1.3.0, but not 2.0.0

* Install the latest version of the dependency package, such as *1.2.3 will match X.X.X,

So how to choose? Of course you can specify a specific version number and write 1.2.3 without any prefix, which is fine, but if a dependency package releases a new version that fixes some minor bugs, you’ll need to manually modify the package.json file. ~ and ^ solve this problem.

However, it should be noted that the ^ version update may be large, which may cause errors in the project code. Therefore, it is recommended to use ~ to mark the version number, so as to ensure that the project will not have major problems, and to ensure that the small bugs in the package can be fixed.

Version number write *, this means that the latest version of the dependency package installed, but shortcomings of the same, may cause version incompatible, caution use!

Dependencies on package installation in multiplayer development

After seeing the version number specified above, we can know that when we use ^ or ~ to control the dependency package version number, multi-developer, there may be the situation that everyone installed the dependency package version is not the same, there will be different results of the project operation.

Let’s take an example:

Assuming we have vUE installed, when we run install NPM install vue-save, the vUE version of package.json in the project is vue: ^3.0.0, the vue version installed on our computer is 3.0.0. After submitting the project code, after some time, vue released a new version 3.0.1. At this time, a new colleague, the new Git Clone project, executed NPM install. The vUE version on his computer is 3.0.1, because ^ only locks the main version so that the VUE version on our computer is different, theoretically (if we all follow semantic version control) they should still be compatible, but maybe bugfix will affect the functionality we are using, And when running with vUE versions 3.0.0 and 3.0.1, our application produced different results.

We think about this, so that different computer installed dependency version of the project, is not likely to be different, will lead to each person’s computer running applications have different results. There is a potential bug.

If you want to lock the version number of the dependency package on package.json, you can do it. Write vue directly: 3.0.0 lock, so everyone installed vue version 3.0.0.

This is a good idea, but you can only control your own project lock version number. What about dependencies in your project? How do you control and restrict others from locking the version number?

Package-lock. json was created to address the need for all dependencies to be consistent across PC installations and to ensure that the project code runs the same during installation.

package-lock.json

Package-lock. json is available after NPM (^5.x.x.x), with several changes along the way

introduce

The official document explains it this way: Package-lock. json is automatically generated when NPM changes the node_modules directory tree or package.json. It accurately describes the dependency tree of the current project’s NPM package. In subsequent installations, package-lock.json will be installed according to the same dependency tree, regardless of whether a dependency has been updated with a minor version.

It is created to version fix (lock) the entire dependency tree.

When we install NPM in a project, a package-lock.json file is automatically generated in the same level of directory as package.json. Package-lock. json records some information about the project and the modules it depends on. This gives the same result every time you install. It doesn’t matter what machine you install it on or when.

The next time we install NPM, NPM will find that if there is a package-lock.json file in the project, it will handle and install dependencies based on the contents of package-lock.json instead of package.json.

Note that when using CNPM install, package-lock.json files are not generated, and dependencies are not installed based on package-lock.json, but are installed using package.json.

Package-lock. json generates logic

Briefly describe the logic generated by package-lock.json. Suppose we now have three packages. In the lock-test project, the installation depends on A, project A has PROJECT B, and project B has project C

// package lock-test
{ "name": "lock-test"."dependencies": { "A": "^ 1.0.0" }}
// package A
{ "name": "A"."version": "1.0.0"."dependencies": { "B": "^ 1.0.0" }}
// package B
{ "name": "B"."version": "1.0.0"."dependencies": { "C": "^ 1.0.0" }}
// package C
{ "name": "C"."version": "1.0.0" }
Copy the code

In this case package-lock.json generates a structure similar to the one paved below

// package-lock.json
{ 
    "name": "lock-test"."version": "1.0.0"."dependencies": {    
        "A": { "version": "1.0.0" },
        "B": { "version": "1.0.0" },
        "C": { "version": "1.0.0"}}}Copy the code

If we do not touch package.json, package-lock.json will not be generated again, either directly dependent version A or indirectly dependent version B or C.

A released A new version 1.1.0, although we write package.json as ^1.0.0, but because of package-lock.json, NPM I will not automatically upgrade,

We can do this manually by running NPM I [email protected].

As [email protected] recorded in 1.1.0 package-lock.json is inconsistent, the version of A in package-lock.json will be updated to 1.1.0.

B released the new version 1.0.1, 1.0.2 and 1.1.0. If we do not do any operation at this moment, the version of B will not be automatically upgraded. But if A released 1.1.1 at this moment, although there is no dependency on upgrading B, if we upgrade [email protected] in our project, At this point, package-lock.json will raise B directly to 1.1.0, because the latest version of ^1.0.0 is now 1.1.0.

After these operations the package.json of the lock-test project becomes

// package 
lock-test{ "dependencies": { "A": "^ 1.1.0." " }}
Copy the code

Corresponding package-lock.json file

{  
    "name": "lock-test"."version": "1.0.0"."dependencies": {  
        "A": { "version": "1.1.0" },
        "B": { "version": "1.1.0" },
        "C": { "version": "1.0.0"}}}Copy the code

At this point we add B to our lock-test dependencies, B@^1.0.0, package.json as follows

{ "dependencies": { "A": "^ 1.1.0." "."B": "^ 1.0.0" }}
Copy the code

Package-lock. json does not change after we perform this operation, because [email protected] now meets the requirements of ^1.0.0 in package-lock.json

But if we fix the version of B to version 2.x, package-lock.json will change

{ "dependencies": { "A": "^ 1.1.0." "."B": "^ 2.0.0." " }}
Copy the code

Because there are two conflicting B versions, the package-lock.json file will look like this

{  
    "name": "lock-test"."version": "1.0.0"."dependencies": {    
        "A": {      
            "version": "1.1.0"."dependencies": {        
                "B": { "version": "1.1.0"}}},"B": { "version": "2.0.0" },    
        "C": { "version": "1.0.0"}}}Copy the code

NPM describes this behavior using nesting because of the conflicting version of B

We do not need to pay attention to the generated algorithm logic in actual development, we only need to understand that the generated logic of package-lock.json is to accurately reflect the structure of our node_modules and ensure that this structure can be restored.

Package-lock. json may have been changed unexpectedly

  1. The package.json file has been modified

  2. Moved the bag

Moving part of the package from dependencies to devDependencies affects package-lock.json and sets the dev field of part of the package to true, although the package does not change

  1. The influence of the registry

After practical use, if we download from the package in node_modules folder, even if the version is the same and the source registry is different, we will modify package-lock.json when executing NPM I

There may be other reasons, but package-lock.json is not changed for no reason, it must be because package.json or node_modules have been changed, As mentioned above, package-lock.json is designed to accurately reflect our node_modules structure

Suggestions for development

NPM install is generally ok, and it can ensure that node_modules are restored from package-lock.json.

However, in order to prevent the unexpected situation just mentioned, it is recommended to use NPM CI to install dependencies in all cases, except when package adjustments are involved, to avoid abnormal changes to package-lock.json.

Continuous integration tools are more recommended to use NPM CI to ensure the accuracy of the build environment. For the difference between NPM I and NPM CI, please refer to the official document NPM-CI

Reference article:

Who changed my package-lock.json?

What file is package-lock.json generated by NPM install? What’s the use?