你想知道关于package-lock.json的一切,但是太害怕了问了?

35次阅读

共计 3709 个字符,预计需要花费 10 分钟才能阅读完成。

简介
如果你已经将节点包管理 (npm) 更新到版本 5.x.x,看起来一切似乎都很顺利。等等,这是什么? 用 npm 初始化项目的会自动创建了一个新文件 package-lock.json。如果打开它,它看起来有点像 package.json 的依赖项,但更冗长。我们决定忽略它,继续开发项目。最终,我们有时会遇到依赖项的问题,找不到,或者安装了错误的版本。大多数人最终都会删 package-lock.json 和运行“npm install”。那么,为什么要有它呢? 它应该做什么? 它实际上是做什么的?
总结

如果你使用的 npm 版本 为 ^5.x.x , package-lock.json 会默认自动生成
你应该使用 package-lock 来确保一致的安装和兼容的依赖关系
你应该将 package-lock 提交到源代码控制
从 npm ^ 5.1.x 开始,package.json 能够胜过 package-lock.json,所以你遇到较少让人头痛的问题
不再删除 package-lock 只是为了运行 npm install 并重新生成它

背景
语义版本控制
在你了解 package-lock 甚至 package.jso n 之前,你必须了解语义版本控制(semver)。这是 npm 背后的天才,是什么使它更成功。你可以在 此处 阅读有关 npm 如何使用它的更多信息。简而言之,如果你正在构建与其他应用程序接口的应用程序,你应该告知你所做的更改将如何影响第三方与你的应用程序交互的能力。这是通过语义版本控制完成的,版本由三部分组成:X,Y,Z,分别是主要版本,次要版本和补丁版本。
例如:1.2.3,主要版本 1,次要版本 2,补丁 3。
补丁中的更改表示不会破坏任何内容的错误修复。次要版本的更改表示不会破坏任何内容的新功能。主要版本的更改代表了一个破坏兼容性的大变化。如果用户不适应主要版本更改,则内容将无法正常工作。
管理包
npm 存在使管理包变得容易。你的项目可能有数百个依赖项,每个依赖项都有一百个,为了让你的注意力远离依赖地狱,通过 npm 管理,使用一些简单的命令,你可以安装和管理这些依赖关系,几乎不必考虑它们。
当您使用 npm 安装包(并保存它)时,会在 package.json 中添加一个包含包名称和应该使用的 semver 的条目。默认情况下,npm 安装最新版本,并预先插入版本号,例如“^1.2.12”,这表示至少应该使用版本 1.2.12,但任何高于此版本的版本都可以,只要它具有相同的主要版本,由于次要版本和补丁编号仅代表错误修正和非破坏性添加,你可以安全地使用任何更高版本的同一主要版本。阅读更多关于 semver 通配符的信息,请看 这里。
共享项目
在 package.json 中定义这样的依赖项的真正好处是,任何有权访问 package.json 的人都可以创建一个包含运行应用程序所需模块的依赖项文件夹,但是让我们来看看事情可能出错的具体方式。
假设我们创建了一个将使用 express 的新项目。运行 npm init 后,我们安装 express:npm install express – save。在编写代码时,最新的版本是 4.15.4,所以“express”:“^ 4.15.4”作为我的 package.json 中的依赖项添加,并且我的电脑安装了确切的版本。
现在也许明天,express 的维护者会发布 bug 修复,因此最新版本变为 4.15.5。然后,如果有人想要为我的项目做贡献,他们会克隆它,然后运行 `npm install。’ 因为 4.15.5 是具有相同主要版本的更高版本,所以为它们安装。我们都安装 express,但我们却是不同的版本。
从理论上讲,它们应该仍然是兼容的,但也许 bugfix 会影响我们正在使用的功能,而且当使用 Express 版本 4.15.4 和 4.15.5 运行时,我们的应用程序会产生不同的结果。
Package-lock
目的
package-lock.json 的目的是避免上述情况,其中从同一 package.json 安装模块会导致两种不同的安装。在 npm 版本 5.x.x 中添加了 package-lock.json,因此如果你使用的是主要版本 5 或更高版本,除非您禁用它,否则它会自动生成。
内容结构
package-lock 是 package.json 中列出的每个依赖项的大型列表,应安装的特定版本,模块的位置(URI),验证模块完整性的哈希,它需要的包列表,以及依赖项列表。让我们来看看 express 的列表是什么:
“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”
}
},

可以在“requires”部分中列出的每个包中找到等效条目。
npm(^5.x.x.x)后的做法,npm 使用 package-lock.json,而不是使用 package.json 来解析和安装模块。因为 package-lock 为每个模块及其每个依赖项指定了版本,位置和完整性哈希,所以它每次创建的安装都是相同的。无论你使用什么设备,或者将来安装它都无关紧要,每次都应该给你相同的结果,这非常有用。
争议
因此,如果引用 package-lock 是希望解决一个常见问题,为什么它的顶级搜索结果(除了 npm 文档)都是关于禁用它或质疑它扮演的角色?
在 npm 5.x.x 之前,package.json 是项目的真实来源,npm 用户喜欢这个模型,并且非常习惯于维护他们的包文件。但是,当首次引入 package-lock 时,它的行为与有多少人预期的相反。给定一个预先存在的包和 package-lock,对 package.json 的更改(许多用户认为是真实的来源)没有同步到 package-lock 中。
示例:包 A,版本 1.0.0 在 package.json 和 package.lock.json 中。在 package.json 中,A 被手动编辑为 1.1.0 版。如果认为 package.json 是真实来源的用户运行 npm install,他们会期望安装 1.1.0 版。但是,安装了 1.0.0 版,即使列出的 v1.1.0 是 package.json,他们也希望安装是 1.0.0 版。
示例:package-lock.json 中不存在模块,但它存在于 package.json 中,作为一个将 package.json 视为真实来源的用户,我希望能够安装我的模块。但是,由于 package-lock.json 不存在该模块,因此未安装该模块,并且我的代码因无法找到模块而失败。
大部分时间,因为我们无法弄清楚为什么我们的依赖关系没有被正确安装,要么删除了 package-lock.json 并重新安装,要么完全禁用 package-lock.json 来解决问题。
期望与真实行为之间的这种冲突在 npm repo 中引发了一个非常有趣的问题线索。有些人认为 package.json 应该是事实的来源,有些人认为,因为 package-lock 是 npm 用来创建安装的东西,所以应该被认为是事实的来源。这场争议的解决方案在于 PR#17508。如果 package.json 已更新,Npm 维护者添加了一个更改,导致 package.json 覆盖 package-lock。现在,在上述两种情况下,都会正确安装用户期望安装的软件包。此更改是作为 npm v5.1.0 的一部分发布的,该版本于 2017 年 7 月 5 日上线。
你的点赞是我持续分享好东西的动力,欢迎点赞!
一个笨笨的码农,我的世界只能终身学习!
更多内容请关注公众号《大迁世界》

正文完
 0