阅读 1797

对npm包精准控制之npm-shrinkwrap.json与package-lock.json

npm-shrinkwrap.json

该文件是通过运行npm shrinkwrap命令产生的,在npm5之前(不包括5),主要是用来精准控制安装指定版本的npm包。具体啥意思?

在开发一个项目的时候,特别是多人协作,或者在不同设备中对同一个项目进行开发,可能会遇到这样的问题,A同事通过npm install安装了一些在某个版本下的npm包,过了一段日子,某个npm包内容功能更新了(更不幸的话还可能是会破坏了原本一些功能的更新),B同事加入项目来了,他也需要在自己的设备上安装项目资源,结果是,在A同事这边功能正常的,但到B同事这边却异常了。这只是一种例子,还有更多类似的,相信很多开发者可能也会遇到过。

那么导致这种情况发生的根本原因是在于,同事间安装的npm包版本不一致,可能功能也就不一致。

可能会有人疑问,那我在package.json中精确写死某个版本的npm包不就得了吗? 不!你漏了一个很重要的信息,这也是package.json做不到的,就是你要安装的这个npm包可能还需要依赖一些其他包,这些其他包的版本你也要控制好才能100%确定一致

还有一个更加典型的例子,就是我们在本地开发好的项目,一切正常,但是当需要在CI上进行打包发布后,发现有bug了!oh shit—— 内心不禁感叹了一下。 原因也是跟上面一样。

那么如何避免这种情况的发生呢,就是要确保安装的npm包版本一致,这时候,就是npm-shrinkwrap.json的作用了,简单看一下长什么样子:

这里边会记录你项目所依赖的npm包的一些信息,如版本号,资源地址,依赖项等,换句话说,就是记录你当前项目所形成的npm资源树。

那记录这些有什么用呢? 我们安装npm包时,依据这些信息来安装对应信息的npm包,以达到每个人安装的包是一致的目的。

注意

  • 每次更新package.json或者node_modules时,如npm install新包,npm updatenpm uninstall等操作,为保持协作人的资源一致,还是要手动运行npm shrinkwrap更新npm-shrinkwrap.json文件的。
  • 而且记得加入到版本控制中,不然就没意义了。
  • shrinkwrap计算时是根据当前依赖安装的目录结构生成的,如果你不能保证package.json文件定义的依赖与node_modules下已安装的依赖是匹配、无冗余的,建议在执行shrinkwrap命令前清理依赖并重新安装(rm -rf node_modules && npm install)或精简依赖(npm prune)。
  • 大家在查阅一些资料时,可能会看到如下描述:

默认情况下,shrinkwrap只计算dependencies依赖,而不计算dev-dependencies,如果在生产环境也需要开发依赖或你的依赖分类不清晰,使用--dev参数生成shrinkwrap文件确保不会出问题。

后来我尝试过,就算不输入--dev,还是可以把开发依赖生成到npm-shrinkwrap.json里,估计当时描述的作者当时背景下,npm这个设置的确是那样,只是到今天的迭代后,已经不正确了。

package-lock.json

在使用npm5后,大家可能都会发现,在项目里会存在一个文件——package-lock.json,打开一看,emmm~~ 这不就是npm-shrinkwrap.json嘛,的确,还真的一摸一样。

这是一个自动生成的文件,在我们修改pacakge.json或者node_modules时就会自动产生或更新了。这个东西不仅长得像npm-shrinkwrap.json,功能也跟它很像。

既然这样,为什么要特意搞这么一个新的文件呢。虽然功能十分十分地相似,但是还是存在一些区别

npm-shrinkwrap.json 与 package-lock.json的区别与联系

从npm版本看

package-lock.json是npm5的新特性,也不向前兼容,如果npm版本是4或以下,那还是使用npm-shrinkwrap.json

从npm处理机制来看

  1. 在一个项目里,如果本身不存在这两个文件,那么在运行npm install时,会自动生成一个package-lock.json,或者在初始化一个项目npm init时,也会生成package-lock.json,安装信息会依据该文件进行,而不是单纯按照package.json,这两个文件的优先级都比package.json
  2. 如果项目两个文件都存在,那么安装的依赖是依据npm-shrinkwrap.json来的,而忽略package-lock.json
  3. 运行命令npm shrinkwrap后,如果项目里不存在package-lock.json,那么会新建一个npm-shrinkwrap.json文件,如果存在package-lock.json,那么会把package-lock.json重命名为npm-shrinkwrap.json

从文件更新来看

  1. npm-shrinkwrap.json只会在运行npm shrinkwrap才会创建/更新
  2. package-lock.json会在修改pacakge.json或者node_modules时就会自动产生或更新了。

从发布包来看

  1. package-lock.json不会在发布包中出现,就算出现了,也会遭到npm的无视。
  2. npm-shrinkwrap.json可以在发布包中出现

疑惑

好吧,我在查阅资料的时候,总有一个不懂的地方,总会看到这么一出描述

建议库作者发布包时不要包含npm-shrinkwrap.json,因为这会阻止最终用户控制传递依赖性更新。

说句实话的,其实我还是不太懂,为啥不要发布呢,这样不就是刚好让发布出来的应用能保证不会由于依赖别人的包更新了而导致出错吗? 恳请大神赐教赐教

本文参考

github.com/npm/cli/blo… ithelp.ithome.com.tw/articles/10… juejin.im/post/684490… blog.csdn.net/ligang25851…