想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!html
若是你已经将节点包管理(npm)更新到版本5.x.x,看起来一切彷佛都很顺利。等等,这是什么?用 npm 初始化项目的会自动建立了一个新文件 package-lock.json
。若是打开它,它看起来有点像 package.json
的依赖项,但更冗长。咱们决定忽略它,继续开发项目。最终,咱们有时会遇到依赖项的问题,找不到,或者安装了错误的版本。大多数人最终都会删package-lock.json
和运行“npm install”。那么,为何要有它呢? 它应该作什么? 它其实是作什么的?前端
npm install
并从新生成它在你了解 package-lock 甚至 package.jso n以前,你必须了解语义版本控制(semver)。 这是npm背后的天才,是什么使它更成功。 你能够在 此处 阅读有关npm如何使用它的更多信息。简而言之,若是你正在构建与其余应用程序接口的应用程序,你应该告知你所作的更改将如何影响第三方与你的应用程序交互的能力。这是经过语义版本控制完成的,版本由三部分组成:X,Y,Z,分别是主要版本,次要版本和补丁版本。git
例如:1.2.3,主要版本1,次要版本2,补丁3。github
补丁中的更改表示不会破坏任何内容的错误修复。 次要版本的更改表示不会破坏任何内容的新功能。 主要版本的更改表明了一个破坏兼容性的大变化。 若是用户不适应主要版本更改,则内容将没法正常工做。express
npm 存在使管理包变得容易。你的项目可能有数百个依赖项,每一个依赖项都有一百个,为了让你的注意力远离依赖地狱,经过 npm 管理,使用一些简单的命令,你能够安装和管理这些依赖关系,几乎没必要考虑它们。npm
当您使用npm安装包(并保存它)时,会在 package.json 中添加一个包含包名称和应该使用的 semver的条目。默认状况下,npm 安装最新版本,并预先插入版本号,例如 “^1.2.12”,这表示至少应该使用版本 1.2.12,但任何高于此版本的版本均可以,只要它具备相同的主要版本,因为次要版本和补丁编号仅表明错误修正和非破坏性添加, 你能够安全地使用任何更高版本的同一主要版本。阅读更多关于semver通配符的信息,请看 这里。json
在 package.json 中定义这样的依赖项的真正好处是,任何有权访问 package.json 的人均可以建立一个包含运行应用程序所需模块的依赖项文件夹,可是让咱们来看看事情可能出错的具体方式。安全
假设咱们建立了一个将使用 express 的新项目。 运行npm init
后,咱们安装express:npm install express - save
。在编写代码时,最新的版本是4.15.4,因此 “express”:“^ 4.15.4”做为个人package.json中的依赖项添加,而且个人电脑安装了确切的版本。cookie
如今也许明天,express 的维护者会发布 bug 修复,所以最新版本变为4.15.5。 而后,若是有人想要为个人项目作贡献,他们会克隆它,而后运行`npm install。'由于4.15.5是具备相同主要版本的更高版本,因此为它们安装。 咱们都安装 express ,但咱们倒是不一样的版本。post
从理论上讲,它们应该仍然是兼容的,但也许bugfix会影响咱们正在使用的功能,并且当使用Express版本4.15.4和4.15.5运行时,咱们的应用程序会产生不一样的结果。
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日上线。
你的点赞是我持续分享好东西的动力,欢迎点赞!