package-lock.json 文件

  今天有同事找到我说,本地js 编译不过,编译不过的代码如下

const host = window?.location?.host || 'localhost';

  是option chaining, 但我本地是编译过的,他把? 删除了,肯定没有问题了,我就没管了。过了几天,又一个同事给我说,他本地也编译不过,也是上面代码引起来。我就觉得奇怪了,有必要找找原因了。

  最新的语法肯定要编译,就和babel 有关,我搜了一个babel option chaining, 都是要加一个插件@babel/plugin-proposal-optional-chaining, 但我们的项目中(.babelrc文件) 并没有这个插件, 那是不是babel-polyfill 或babel running time做了什么?在搜索babel running time的时候,发现了add optional chanining to preset-env 的信息。点过去, 看到optional chanining 添加到babel 的githup 分支讨论,最终merge了,merge 的版本是7.8.0,也就是说 最新的@babel/preset-env已经包含了optional chaining。 对于使用者来说,就是如果本地安装的@babel/preset-env大于7.8.0 就可以直接使用option chaining,如果小于就有问题了,我赶紧让同事查了一下它安装的版本,果然,他本地的安装的版本是7.7.0。升级一下,就没有问题了,本地编译也通过了。同一个包,在不同的机器上安装,会有不同的版本,这让我想到了package-lock.json 文件。以前也是觉得它没什么作用,现在需要重新认识一下了。

  在说package-lock.json 之前,先说一下npm 包的版本号。它有三部分组成:x.y.z. x是大版本,y是小版本,z是补丁版本。比如react 的版本号:16.10.2。 那么16 就是大版本,10就是小版本,2是补丁版本。补丁版本通常是一些bug的修复,功能不会改变。小版本通常是增加了一些新功能,也不会破坏以前的功能。大版本就不一样了,可能把某些过时的功能上删掉了,就会和以前的版本不兼容,通常是破坏性升级。

  npm在安装包的时候(npm install xxx --save, npm install xxx --save-dev),它会在package.json的dependencies 和devDependencies 中列出安装的包名,还有版本号。默认情况下,它会从npm仓库中安装最新的版本,并且在版本号前面加^

 "dependencies": {
    "react": "^16.10.2",
    "react-dom": "^16.10.2",
    "react-scripts": "3.2.0"
  },

"devDependencies": {
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.14.0"
  }

  ^ 表示最小版本。使用16.10.2 版本,但大于这个版本的也ok, 只要使用相同的大版本号。因为小版本和补丁版本通常是一些bug修复和没有破坏性的添加,只要大版本号没有发生变化,使用相对高一点的版本也是安全的。

  在package.json 中保存依赖,确实带来了好处,任何人拿到项目时,使用npm install 就可以安装整个项目的依赖包,而不用相互之间传递node_modules。但这同样会带来一个小问题,每个人在自己的电脑上安装的同一个包的版本可能会不同。就比如上面提到的@babel/preset-env. 当我在开发项目的时候,版本号可能是7.7.0。 npm i @babel/preset-env --save-dev.那么在package.json文件夹中,就会被记录下来 “@babel/preset-env”: “^7.7.0”, 同时项目中真正安装的版本是7.7.0. 不久之后,项目上传到git. 同事开始合作开发,他git clone, npm install.  这时@babel/preset-env可能升级了几个版本,比如7.9.0. 他npm install, 真正安装的版本是7.9.0. 通常没有问题,但如果他在开发项目的过程中,使用了7.9.0 中的内容(option chaining )。当我git pull把代码拉取下来,本地编译 就会报错,因为我本地的node_module中的版本7.7.0 中没有这个功能。不同的机器上,不同的版本,导致的问题就是为什么在我的电脑上跑不起来。

   package-lock.json 就是解次这个问题的,它列出了整个项目准确的依赖。npm i @babel/preset-env --save-dev, 虽然在package.json 中记录的是“^7.7.0”, 但是package-lock.json中记录的却是精确的版本号,当时开发时从npm 仓库下载的版本。如下所示version:7.7.0, 并且reslove 都记录了包的下载地址。The goal of package-lock.json is to keep track of the exact version of every package that is installed so that a product is 100% reproducible in the same way even if packages are updated by their maintainers.

 "@babel/preset-env": {
      "version": "7.7.0",
      "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.7.0.tgz",
      "integrity": "sha1-q7s+14XH/kIg1MgqU2IdcfwMddM=",
      "requires": {

  npm install 在安装依赖的时候,它会优先解析package-lock.json. 那每个人安装的版本就是一样的。那这又带来了一个问题,每个人的电脑上都安装的7.7.0 版本,那我想升级怎么办?要使用新的功能怎么办?有两个办法

  1,手动安装要更新的包,比如@babel/preset-env.  npm i @babel/preset-env --save-dev, 这时会从npm 仓库拉取最新的包,并同步更新package.json 和package-lock.json

  2,手动更改package.json, 然后npm install, 这时npm会根据package.json 安装新的版本,package-lock.json 也会同步进行更新。

  如果package.json 发生变化,和package-lock.json 中的版本不一致,npm 会依据package.json 安装依赖,并同步更新package-lock.json

   稍微总结一下, package.json 文件记录了整个项目开发要用到的依赖,package-lock.json 则是记录开发者在开发时的准确依赖。如果没有package-lock 文件,npm install 的时候,它永远会从npm 仓库下载最新的依赖。Without a package lock file, a package manager such as  npm will resolve the the most current version of a package in real-time during the dependencies install of a package, rather than the version that was originally intended for the specific package.

posted @ 2020-04-20 22:28  SamWeb  阅读(344)  评论(0编辑  收藏