本文讲的是[译] 理解 NPM 5 中的 lock 文件,
  • 原文地址:Understanding lock files in NPM 5
  • 原文作者:Jiří Pospíšil
  • 译文出自:掘金翻译计划
  • 译者:Changkun Ou
  • 校对者:JackGit, Aladdin-ADD

理解 NPM 5 中的 lock 文件

NPM 的下个主版本(NPM 5)在速度、安全性和一堆其他时髦的东西上,相比较前一个版本带来了一些改进。然而从用户的角度来看,最突出的就是全新的 lock 文件,不止一个 lock 文件。我们一会儿再谈论这个。对于新手来说,一个 package.json 文件使用了语义化版本规范,去描述对于其他包的直接依赖,而这些包可能依赖于其他包等等,以此类推。lock 文件则是整个依赖关系树的快照,包含了所有包及其解析的版本。

与之前版本相反,lock 文件现在包含一个 integrity 字段,它使用 Subresource Integrity 来验证已安装的软件包是否被改动过,换句话来说,验证包是否已失效。它依旧支持旧版本 NPM 中对包的加密算法 SHA-1,但是以后将默认使用 SHA-512 进行加密。

这个文件目前取消了 from 字段。众所周知,这个字段和时常发生不一致的 version 字段一起,给代码审查看文件改动差异时,带来了不少痛苦。不过现在应该变得更加整洁了。

该文件现在增加了 lockfileVersion 字段来指定的 lock 格式的版本,并将其设置为1。这是为了使将来的格式更新时,不用去猜测该文件使用什么特定版本。以前的 lock 格式仍然支持并被识别为版本 0

{"name": "package-name","version": "1.0.0","lockfileVersion": 1,"dependencies": {"cacache": {"version": "9.2.6","resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz","integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg=="},"duplexify": {"version": "3.5.0","resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz","integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=","dependencies": {"end-of-stream": {"version": "1.0.0","resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz","integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4="},

你可能已经注意到了,指向特定 URI 的文件的 resolved 字段仍然得到了保留。注意,NPM 现在可以(根据 .npmrc 中的设置)解析机器配置使用的不同仓库,这样的话,与 integrity 字段一起配合,只要签名是匹配的,包的来源并无关紧要。

值得一提的是,lock 文件精确描述了 node_modules 目录中所列出的目录的物理树。其优点是,即使不同的开发人员使用不同版本的 NPM,他们仍然不仅能够得到相同版本的依赖,还可以使用完全相同的目录树。 这与其他包管理器(如 Yarn )不同。 Yarn 仅以 flatten 格式 描述各个包之间的依赖关系,并依赖于其当前实现来创建目录结构。这意味着如果其内部算法发生变化,结构也会发生变化。如果你想了解更多关于 Yarn 和 NPM 5 之间 lock 文件的区别,请查看 Yarn determinism。

双 lock 文件

上面已经提到过 lock 文件不止一个。当安装新的依赖关系或文件不存在时,NPM 将自动生成一个名为 package-lock.json 的 lock 文件。如开始所述,lock 文件是当前依赖关系树的快照,允许不同机器间的重复构建。因此,建议将它添加到您的版本控制中去。

你可能会认为,使用 npm shrinkwrap 及其 npm-shrinkwrap.json 可以实现同样的效果。你的想法没错,但创建新 lock 文件的原因是,这样能够更好的传达一个信息,就是 NPM 真正支持了 locking 机制,这在以前确实是一个显著的问题。

不过还是有一些区别。首先,NPM 强制该 package-lock.json 不会被发布。 即使你将其显式添加到软件包的 files 属性中,它也不会是已发布软件包的一部分。这种情况同样不适用于npm-shrinkwrap.json 文件,哪怕这个文件可以是发布包的一部分、即便存在嵌套的依赖关系,NPM 也会遵守它。你可以简单的通过运行 npm pack 来查看生成的归档内部的内容。

接下来,您可能会想知道在已经包含 package-lock.json 的目录中运行 npm shrinkwrap 时会发生什么。答案很简单,NPM 仅仅会把 package-lock.json 重命名为 npm-shrinkwrap.json。因为文件的格式是完全一样的。

最好奇的还会问,当两个文件都存在时会发生什么。 在这种情况下,NPM将完全忽略package-lock.json,只使用 npm-shrinkwrap.json。 当只使用 NPM 操纵文件时,这种情况不应该发生。

总结:

  • NPM 会在安装包时自动创建 package-lock.json,除非已经有 npm-shrinkwrap.json,并在必要时更新它。

  • 新的 package-lock.json 永远不会被发布,而且应该将其添加到你的版本控制系统中去。

  • 运行已经带有 package-lock.json 文件的 npm shrinkwrap 命令将只会对其重命名为 npm-shrinkwrap.json

  • 当两个文件处于某些原因同时存在时,package-lock.json 将被忽略。

这很酷,但是什么时候使用新的 lock 文件而不是旧的 shrinkwrap? 它通常取决于您正在处理的包的类型。

当开发库时

如果你正在开发一个库(如其他人所依赖的软件包),则应使用新的 lock 文件。 另一种替代方案是使用 shrinkwrap,并确保它不会随包发布(新的 lock 文件不会自动发布)。 但为什么不发布 shrinkwrap 呢? 这是因为 NPM 遵守在包中找到的 shrinkwraps,并且由于 shrinkwrap 总是指向单个包的特定版本,所以你无法利用 NPM 可以使用相同的包来满足多个包的要求(在 semver 允许范围内)的优势。 换句话说,通过不去强制 NPM 来安装特定的版本,您可以让 NPM 更好的复用包,并使结果更小更快地组合。

这里有一个警告。当你正在开发库时,因为仓库中存在 package-lock.json 或 npm-shrinkwrap.json,所以每次都会获得完全相同的依赖关系,这对于你的持续集成服务器也是如此。现在想象你的 package.json 指定某个包的依赖关系为 ^1.0.0,也恰好是 lock 文件中指定的版本,并且每次安装。到目前为止一切正常。但如果依赖项发布了一个新版本,并且意外的破坏了 semver 和你开发的包,这时候会发生什么?

遗憾的是,在出现错误报告之前,你可能无法注意到这个问题。在没有 lock 文件的仓库中,你的构建至少在 CI 服务器上会失败,因为它总是尝试去安装依赖的 latest 版本,从而运行出错的版本(只要该版本定期运行,而不仅仅是针对 PR)。 然而,当 lock 文件出现后,它将始终安装能正常工作的被 lock 的版本。

然而,对于这个问题有几个其他的解决方案。 首先,你可以牺牲问题重现的精确性,而不将 lock 文件添加到版本控制系统中。 其次,你可以做一个分离的配置来进行构建,在运行测试之前运行 npm update。 第三,你可以简单的在你运行测试之前删除 lock。 如何处理发现的损坏依赖是另一个话题了,其主要原因是因为 NPM 实现的 semver 不仅没有涉及如此广范围的问题,而且还不支持特定版本的黑名单特性。

这当然就会引起一个问题,在开发库的时候,是否真的值得将 lock 文件添加到版本控制中去。要记住的是,lock 文件不仅包含依赖关系,还包含 dev 的依赖关系。在这种意义下来讲,开发库与开发应用时类似(见下一节),无论什么时候都有着完全相同的 dev 依赖关系,并且不同设备也算一种优势。

当开发应用时

好,那么最终用户在终端中使用的包或打包的可执行文件会是个什么情况?在这种情况下,包就是最终结果,即应用。你想要确保最终用户总能获得你发布时所具有的确切依赖性。确保在安装时让 NPM 遵守规则,这就是您想要使用 shrinkwrap 的地方。 记住,使用 npm pack发布包时,你可以随时查看软件包的情况。

注意,在 package.json 中指定一个特定版本依赖是不够的,因为你希望确保最终用户获得完全相同的依赖关系树,包括其所有子依赖关系。而 package.json 中的一个特定版本保证只会发生在顶层。

其他类型的应用怎么样,比如在仓库内启动的项目?这种情况并不重要。重要的是安装正确的依赖项,而两个 lock 都满足这一点要求。随你怎么选。

结束

没了,就这么多。如果有哪里不对或者有一些一般性的意见,请随时在 Twitter 上联系我。如果你发现拼写错误或语法问题,则可以在 GitHub 上找到这个文章。感谢你的帮助!






原文发布时间为:2017年6月16日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。

[译] 理解 NPM 5 中的 lock 文件相关推荐

  1. mysql漏洞包_MySQL npm包中的本地文件泄露漏洞

    "A pure node.js javascript Client implementing the MySQL protocol." 漏洞 在某次安全评估中,Synacktiv专 ...

  2. linux中的lock文件,linux – 为什么即使文件被锁定,File :: FcntlLock的l_type总是“F_UNLCK”?...

    下面的Perl子例程使用File :: FcntlLock来检查文件是否被锁定. 为什么它返回0并且打印/tmp/test.pid被解锁.即使文件被锁定了? sub getPidOwningLock ...

  3. 如何理解Linux shell中的“2>1”(将文件描述2(标准错误输出)的内容重定向到文件描述符1(标准输出))(尼玛>符号竟然不支持搜索,害我搜搜不到,只能搜)

    文章目录 前言 有何妙用 如何理解 总结 前言 有时候我们常看到类似这样的脚本调用: ./test.sh > log.txt 2>&1 这里的2>&1是什么意思?该如 ...

  4. xml文件 卷积神经网络_理解卷积神经网络中的输入与输出形状(Keras实现)

    即使我们从理论上理解了卷积神经网络,在实际进行将数据拟合到网络时,很多人仍然对其网络的输入和输出形状(shape)感到困惑.本文章将帮助你理解卷积神经网络的输入和输出形状. 让我们看看一个例子.CNN ...

  5. 把庞大的 npm script 拆到单独文件中

    把庞大的 npm script 拆到单独文件中 当 npm script 不断累积.膨胀的时候,全部放在 package.json 里面可能并不是个好主意,因为这样会导致 package.json 糟 ...

  6. 企业会计准则2020版pdf_2020年下半年CATTI三级笔译中译英真题+参考答案+原文件汉英对照PDF版...

    当今世界,以互联网为代表的信息技术日新月异,引领了社会生产新变革,创造了人类生活新空间,拓展了国家治理新领域,极大提高了人类认识世界.改造世界的能力. Today, the rapid advance ...

  7. SAP中状态参数文件最高状态和最低状态的理解

    在SAP中订单的应用还是比较广泛的.如下图所示:生产订单,内部订单,质量订单,成本收集器等. 而这些类型的订单在系统后台的定义界面都基本相似.这说明虽然订单的类型有不同,但其结构和应用原理基本相似:针 ...

  8. 面试问题-理解数字后仿,其次针对性理解数字后仿中的sdf文件(约束文件)的作用

    理解数字后仿,其次针对性理解数字后仿中的sdf文件(约束文件)的作用 1)什么是sdf文件 2)如何反标sdf文件? 1,什么是数字后仿? 2,什么是门级网表? 3,什么是sdf文件 4,如何反标sd ...

  9. C++:include:理解 C++ 中的头文件和源文件的作用

    关于头文件和源文件我们主要围绕: C++编译模式, 声明和定义区别, 符号只能被定义一次, 符号被定义在多个源文件,但是一个源文件只能定义一次 这四个方面来分析论述 1:C++ 编译模式 在一个C++ ...

最新文章

  1. 【ES6】Module模块详解
  2. python修改数据库_python mysql修改数据库数据库
  3. vim之格式化代码功能——gg=G
  4. C#中创建、打开、读取、写入、保存Excel的一般性代码
  5. for oracle中pivot_oracle关键字pivot行转列【坑爹的三小时,动脑经真累 】 | 学步园...
  6. Lucene 与 Elastic
  7. 1 数列分块入门_LOJ#6277.数列分块入门1
  8. UCan下午茶武汉站,为你全面挖宝分布式存储
  9. SSH:Struts + Spring + Hibernate 轻量级Java EE企业框架
  10. 磁盘设置压缩导致无法将数据库还原到该硬盘的问题
  11. QString与std::string 有中文时的转换操作
  12. Ubuntu 下的PDF阅读器
  13. 《托马斯微积分》阅读笔记2
  14. 12864液晶模块的详细使用
  15. Python识别图片中数字/数值的方法笔记
  16. SQL 事务(Tran | Transation)与 Try...Catch 的使用
  17. github上如何下载单个文件
  18. 电脑怎么连接隐藏的无线WiFi信号呢
  19. 无需关注微信公众号破解openwrite验证
  20. 无人驾驶计算机控制系统,自动驾驶汽车的无人驾驶系统三大模块是什么?

热门文章

  1. Remoting 与 Webservice 的区别
  2. linux android ndk r9b JNI 开发过程(COCOS2D-X配置)
  3. 整理javascript操作文件说明:读写文件
  4. 【Groovy】Groovy 脚本调用 ( Groovy 类中调用 Groovy 脚本 | 创建 GroovyShell 对象并执行 Groovy 脚本 | 完整代码示例 )
  5. 【Java 虚拟机原理】垃圾回收算法 ( 可达性分析算法 | GC Root 示例 | GC 回收前的两次标记 | finalize 方法示例 )
  6. 【字符串】字符串查找 ( 蛮力算法 )
  7. 【Android APT】编译时技术 ( ButterKnife 原理分析 )
  8. android中Invalidate和postInvalidate的区别
  9. CDQ分治嵌套模板:多维偏序问题
  10. iptables 工具的使用