package-lock.json

package-lock.json

三月 20, 2018

什么是package-lock.json,为什么会出现这个文件,使用的时候的注意事项

什么是package-lock.json

npm5之后执行npm install会自动生成一个文件package-lock.json,打开这个文件,可能长这样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "ad-portal2.0",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@ant-design/colors": {
"version": "6.0.0",
"resolved": "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-6.0.0.tgz",
"integrity": "sha1-m5NmJXz/zEfbQrnQIDu1ksE8Apg=",
"requires": {
"@ctrl/tinycolor": "^3.4.0"
}
},
}
}

官方给出的解释:package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.

翻译一下:package-lock.json是当npm改变的时候自动生成的一个文件,不论是改变node_modules树还是package.json,它描述了确切的生成的一颗树,以至于保证后续的install能够生成相同的树,不考虑中间依赖项更新

简单来说,package-lock.json就是锁定安装时的包的版本号,以保证其他人在npm install时大家的依赖能保持一致。它甚至还记录了包下载的地址

背景

package.json

先从package.json说起:package.json就是管理 npm 包的文件,包含了项目所依赖的 npm 包、项目的配置信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "test",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
},
"devDependencies": {
"babel-plugin-import": "^1.13.3",
},
"scripts": {},
"eslintConfig": {},
"browserslist": {},
...
}

当我们执行 npm istall xxx的时候就会在dependencies或者devDependencies中增加一个包的名字加版本号的记录

semver语义化的版本号

上面的package.json中每一个包都有自己的版本号,是我们安装时候的版本号,使用的是semver语义化的版本号规则,他是npm包管理的精髓。

什么是semver语义化的版本号?

"react": "^17.0.2",比如这个包的版本号

版本号主要包含:版本符号(^),主版本号(X),次版本号(Y),补丁更新(Z)

  • 补丁更新:当前版本下的bug修复,补丁更新的数字加1

  • 次版本号:增加新功能,且不破坏原有的功能,次版本号的数字加1

  • 主版本号:重大修改,可能不兼容旧的功能,主版本号加1

版本符号,用来做版本的控制:

  • ^:默认,使用npm install安装包的时候,会自动在版本号前面加这个符号,表示保护主版本号不变

  • ~:可以手动的修改^为~,表示保护次版本号不变

  • :主要是用来指定可以安装beta版本

例如:

"react": "^17.0.2",当我们执行npm install的时候,只能在保证主版本号不变的情况下安装最新版本的包。

"react": "~17.0.2",当我们执行npm install的时候,只能在保证次版本号不变的情况下安装最新版本的包。

package.json的问题

一般的开发过程,我们是不会把node_modules这个文件提交到代码仓库,而是通过package.json来存储包的依赖,然后当在另外一台电脑上想要运行项目的时候,就会从git仓库把代码拉下来,本地执行npm install,重新安装包。这个时候就会出现问题

例如我们在安装的时候react的版本是17.0.2,我们的package.json中react的版本号是"react": "^17.0.2",然后在另外一台电脑上install的时候会默认在保持17这个主版本号不变的情况下下载最新的版本的包,正好这个时候react从17.0.2升级到了17.1.1,然后17.1.1或许会有bug,然后在新的电脑上运行项目就会报错了。

虽然我们可以手动改变react的版本号,但当我们的依赖变的很多的而且有嵌套关系的时候,手动修改就会变的很麻烦,package-lock.json的出现就是为了解决这个问题,因为它会锁定安装时候的版本号,保证所有的人在install的时候都能安装到相同的包

锁版本号

有了package-lock.json,我们需要把它提交到代码仓库,这样子就保证了在每一台电脑上install的时候都能安装到相同版本的包,那么该如何使用呢?

搭建一个demo项目来尝试一下:

  1. 新建空的目录 package-test

  2. 命令终端进入这个目录,输入命令npm init -y会车,生成package.json文件,如下

  3. 安装一个包来测试,npm install react@15.0.0,安装一个react的指定版本15.0.0

安装完react的15版本之后,package.json会增加一个包的信息,版本的符号是默认的^

1
2
3
"dependencies": {
"react": "^15.0.0"
}

并且根目录下自动出现了package-lock.json文件,react版本

1
2
3
4
5
6
7
8
9
10
"react": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/react/-/react-15.0.0.tgz",
"integrity": "sha1-PH4WUx1jDhXBpQqUfxS6YXRq+Kc=",
"requires": {
"fbjs": "^0.8.0",
"loose-envify": "^1.1.0",
"object-assign": "^4.0.1"
}
},

根目录下还生成了一个node_modules文件夹,里面的react也是15.0.0版本

这个项目主要是测试package.json和package-lock.json的功能,不用来运行,简单一下就好

不使用package-lock.json

手动的删除package-lock.json文件夹,以禁用package-lock.json

手动删除node_modules文件夹,假装是在另一台电脑上重新install,执行 npm install,发现根目录再次自动生成了package-lock.json,

查看package.json,里面的react的包的版本号不变还是15.0.0

查看package-lock.json,里面的react的包的版本号变成了15.7.0,node_modules文件夹,里面的react也是15.7.0版本,

因为package.json里面react的版本符号是^,所以在执行install的时候能够保证主版本号不变,npm会为我们安装当前主版本号下面最新的包,也就是15.7.0,而这不是我们想要的

使用package-lock.json

使用上面的方法再次搭建一个新的demo项目,这次不删除package-lock.json,

手动删除node_modules文件夹,假装是在另一台电脑上重新install,重新执行 npm install

查看package.json,里面的react的包的版本号不变还是15.0.0,

查看package-lock.json,里面的react的包的版本号还是15.0.0,node_modules文件夹,里面的react也是15.0.0版本,

这似乎达到了我们的想要的目的

手动修改package.json

我们想要升级一个npm包,直接修改package.json里面的版本号,然后执行npm install,

比如我现在把package.json里面的react的版本号直接改成16.0.0

1
2
3
"dependencies": {
"react": "^16.0.0"
}

而package-lock.json,里面的react的包的版本号还是15.0.0,

这个情况是package-lock.json和package.json里面的版本号不一样了,执行npm install之后会出现什么情况呢?

手动删掉node_modules文件夹,假装是在另一台电脑上重新install,重新执行 npm install,

查看package.json,里面的react的包的版本号不变还是16.0.0,

查看package-lock.json,里面的react的包的版本号还是16.14.0,node_modules文件夹,里面的react也是16.14.0版本,

由此可以看出,当我们执行npm install 的时候,npm会首先查看package-lock.json里面的依赖版本,然后查看package.json里面的版本,如果两者一致则按照package-lock.json的版本安装,如果两者冲突会以package.json为主,并且更新package-lock.json里面的版本号

如何锁版本号

为了避免出现无意的更新package-lock.json,我们可以不使用版本符号,锁定版本:

1
2
3
"dependencies": {
"react": "16.0.0"
}

重新执行 npm install,

查看package.json,里面的react的包的版本号不变还是16.0.0,

查看package-lock.json,里面的react的包的版本号还是16.0.0,node_modules文件夹,里面的react也是16.0.0版本

当我们想要使用某个包的最新的版本的代码的时候可以手动执行 npm update xxx@版本号来安装最新的版本或者安装指定版本的包

这个操作会重写package-lock.json文件