欢迎各位兄弟 发布技术文章
这里的技术是共享的
把npm更新到v5.x.x以后, 会出现一种新的自动生成文件 - Package-lock.json. 如果打开这个文件, 会发现它看着像package.json里面的依赖.
在解package.json
和package-lock.json
前, 需要先了解semver 语义化版本号变更. 它是npm依赖管理背后的精髓. 点这里了解npm是如何使用它的. 总的来说, 所谓的语义化版本号变更, 就是当你修改了你所维护的第三方库时, 告诉那些使用了你的库的项目, 你做的是哪种修改. 一个版本号分为三个部分: X,Y,Z. X表示主版本号, Y表示次版本号, Z表示补丁更新. 当你只是简单的修复了BUG, 没有做任何新功能的添加, 或者旧功能的修改, 就需要更新补丁号(数值加一等等). 当你添加了新的功能, 但没有破坏原有的功能, 就需要更新次版本号. 当你做了重大修改导致新版本不兼容旧的代码时, 就需要更新主版本号.
^
是npm默认的版本符号, 当你使用npm install --save
时, npm会自动在package中添加^
加上版本号. 例如: npm install --save angular
会在package.json中添加"angular": "^1.3.15"
.这个符号会告诉npm可以安装1.3.15
或者一个大于它的版本, 但是要是主版本1
下的版本.
~
同样被用来做npm得版本控制, 例如~1.3.15
, 代表了npm可以安装1.3.15
或者更高的版本, 与^
的区别在于, ~
的版本只能开始于次版本号1.3
. 它们的作用域不同. 你可以通过npm config set save-prefix='~'
将~
设置为默认符号.
>
符号主要是用来指定可以安装beta版本.
当你添加了一个依赖时, package.json
里面会加一项条目, 包含包的名称, 并且使用semver来处理版本号. npm支持版本号中包含通配符. 一般来说, npm会安装最新的版本的依赖, 并且在版本号前面加上^
符号, 比如^1.2.12
. 这表示, 至少要安装1.2.12
的版本, 但更高的版本也可以, 只要主版本号也为1就行. 因为补丁号和次版本号的变动不会变更已有的API. 你应该可以安全地使用任何主版本一致的更高版本依赖. 你可以点击这里的版本计算器, 了解通配符的含义.
把依赖记录在package.json里面的优点是, 只要别人可以访问package.json, 他就可以安装里面所记录的依赖, 然后就可以直接运行你的项目了. 不过有些时候, 这样子会出现一个问题.
比如我们的项目用了express这个框架. 我们使用npm init初始化项目后, 使用命令npm install express --save安装了依赖. express的版本号是4.15.4, 所以package.json里面express的版本号会是^4.15.4, 然后电脑上面就安装了版本为4.15.4的express. 然后可能第二天, express的维护者修复了一个BUG, 现在最新版本变成了4.15.5. 接着, 有个人觉得我们的项目很不错, 他想贡献一些代码, 于是它clone下来, 运行了npm install. 由于最新express版本是4.15.5, 并且主版本号也是一致的, 因此他的电脑上安装的版本就是4.15.5. 我们都安装了express, 但是版本却不一样.
理论上来说, 这两个版本应该是兼容的, 但是可能那个修复的BUG影响到了我们所使用的功能, 使得在这两个不同的版本上出现不同运行结果.
package-lock.json诞生的目的是为了防止出现我们上述的情况. 同一个package.json却产生了不同的运行结果. package-lock.json在npm 5时添加进来, 所以如果你使用5以上的版本, 你就会看到这个文件, 除非你手动禁用掉它. 所以从此以后npm会根据package-lock.json里的内容来处理和安装依赖而不是根据package.json. 因为pacakge-lock.json给每个依赖标明了版本, 获取地址和哈希值, 使得每次安装都会出现相同的结果. 不管你在什么机器上面或什么时候安装。
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. This file is intended to be committed into source repositories, and serves various purposes.
大概意思是, 当我们对node_modules或者package.json进行了更改后, package-lock.json文件会自动生成. 里面会描述上一次更改后的确切的依赖管理树. 里面包含了唯一的版本号和相关的包信息. 之后的npm install
会根据package-lock.json文件进行安装, 保证不同环境, 不同时间下的依赖是一样的.
还有一个好处是, 由于package-lock.json文件中记录了下载源地址, 可以加快我们的npm install
速度
package-lock.json是一个包含你所有依赖的巨大列表, 它包含明确的版本号(没有通配符), 依赖的获取地址, 一个用于验证完整性和正确性的哈希值, 以及这个依赖本身所需要的依赖.
"express": {
"version": "4.15.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
"integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
"requires": {
"accepts": "1.3.3",
"array-flatten": "1.1.1",
"content-disposition": "0.5.2",
"content-type": "1.0.2",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.8",
"depd": "1.1.1",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.0",
"finalhandler": "1.0.4",
"fresh": "0.5.0",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.1",
"path-to-regexp": "0.1.7",
"proxy-addr": "1.1.5",
"qs": "6.5.0",
"range-parser": "1.2.0",
"send": "0.15.4",
"serve-static": "1.12.4",
"setprototypeof": "1.0.3",
"statuses": "1.3.1",
"type-is": "1.6.15",
"utils-merge": "1.0.0",
"vary": "1.1.1"
}
},
来自 https://www.jianshu.com/p/818833b2dd5a
其实用一句话来概括很简单,就是锁定安装时的包的版本号,并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致。
引用知乎@周载南的回答
根据官方文档,这个package-lock.json 是在 `npm install`时候生成一份文件,用以记录当前状态下实际安装的各个npm package的具体来源和版本号。
它有什么用呢?因为npm是一个用于管理package之间依赖关系的管理器,它允许开发者在pacakge.json中间标出自己项目对npm各库包的依赖。你可以选择以如下方式来标明自己所需要库包的版本
这里举个例子:
"dependencies": {
"@types/node": "^8.0.33",
},这里面的 向上标号^是定义了向后(新)兼容依赖,指如果 types/node的版本是超过8.0.33,并在大版本号(8)上相同,就允许下载最新版本的 types/node库包,例如实际上可能运行npm install时候下载的具体版本是8.0.35。波浪号
大多数情况这种向新兼容依赖下载最新库包的时候都没有问题,可是因为npm是开源世界,各库包的版本语义可能并不相同,有的库包开发者并不遵守严格这一原则:相同大版本号的同一个库包,其接口符合兼容要求。这时候用户就很头疼了:在完全相同的一个nodejs的代码库,在不同时间或者不同npm下载源之下,下到的各依赖库包版本可能有所不同,因此其依赖库包行为特征也不同有时候甚至完全不兼容。
因此npm最新的版本就开始提供自动生成package-lock.json功能,为的是让开发者知道只要你保存了源文件,到一个新的机器上、或者新的下载源,只要按照这个package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。
原来package.json文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几乎是不敢随意升级依赖包的,这将导致多出来很多工作量,测试/适配等,所以package-lock.json文件出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本。
那如果我们安装时的包有bug,后面需要更新怎么办?
在以前可能就是直接改package.json里面的版本,然后再npm install了,但是5版本后就不支持这样做了,因为版本已经锁定在package-lock.json里了,所以我们只能npm install xxx@x.x.x 这样去更新我们的依赖,然后package-lock.json也能随之更新。
假如我已经安装了jquery 2.1.4这个版本,从git更新了package.json和package-lock.json,我npm install能覆盖掉node_modules里面的依赖吗?
其实我也有这个疑问,所以做了测试,在直接更新package.json和package-loc.json这两个文件后,npm install是可以直接覆盖掉原先的版本的,所以在协作开发时,这两个文件如果有更新,你的开发环境应该npm install一下才对。