在执行npm init
的时候,项目中会生成package.json
文件。
{
"name": "test-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/react": "^16.14.14",
"@types/react-dom": "^16.9.14",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"typescript": "^3.8.3"
},
"devDependencies": {
"@storybook/react": "^6.3.7",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"less": "^4.1.2",
"less-loader": "^5.0.0",
"style-loader": "^1.3.0",
"ts-loader": "^6.0.4"
}
}
我们安装的依赖会根据-D
参数来记录在在dependencies
或devDependencies
中,如:
"dependencies": {
"@types/react": "^16.14.14",
"@types/react-dom": "^16.9.14",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"typescript": "^3.8.3"
},
其中key为依赖包名,后面的value为安装的版本号。
package.json
中支持以semve
r表示法来更新升级所需要的依赖版本。
- ~16.13.1表示只更新补丁版本,即16.13.2可以,16.14.0不可以
- ^16.13.1表示更新补丁版本和次版本,即16.14.0和16.13.2都可以
- 16.13.1表示始终使用该版本
然而,在我们的项目中本地使用的版本为^16.13.1
,package.json中也记录了^16.13.1
。在把项目上传到github的时候,一般不会将node_modules
一起上传,然而在别人拉取我们项目的时候需要npm install
来安装相关的依赖,由于package.json
一般不会指定具体版本,所以^16.13.1
在安装的时候可能会安装成^16.13.2
。所以会造成一个问题:不同开发者拉取的同一个项目,安装的依赖版本可能不相同,可能会带来一些接口的兼容问题或更新后的某些行为特征不一样。这时候我们需要package-lock.json
来帮助我们指定版本,避免不必要的环境错误。
同一个依赖,在package-lock.json
中是这样记录的:
"react-dom": {
"version": "16.13.1",
"resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-16.13.1.tgz",
"integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.19.1"
}
},
其中resolved
保存了npm registry
安装的依赖的tgz包地址,integrity
是用于校验的hash值,requires
记录了该依赖相应的子依赖。
有了package-lock.json
,在每次npm install
的时候,npm会比较两个文件,如果package.json
和package-lock.json
中的依赖版本兼容,那会安装package-lock.json
中的下载;如果不兼容,会根据package.json
中的版本更新package-lock.json
,再进行下载。package-lock.json
的存在使得node不会自动更新package.json
,必须强制指定版本安装。
为什么需要package-lock.json而不是在package.json指定一个版本?
在package.json
中指定模块版本,只能指定”最外层”的版本。比如将A模块固定为1.0.0版本,然而A模块依赖的B、C版本还是不受约束的^写法,如果B、C版本更新了这样也会引发类似的兼容问题。
参考:
- https://segmentfault.com/a/1190000023729582
- http://nodejs.cn/learn/the-package-lock-json-file
- https://www.cnblogs.com/goloving/p/14602743.html
- https://www.cnblogs.com/yalong/p/15013880.html