什么时候我们不应该使用锁文件

栏目: Node.js · 发布时间: 4年前

内容简介:调试程序时遇到的最常见情景之一可能是“在我的电脑上明明是好的”。这通常是由于对程序带有bug和自己系统的底层依赖不同的结果。 因此,yarn和npm在引入了的“lock files”,可以跟踪依赖项的确切版本。但是,当您开发将发布到npm的包时,应避免使用此类锁文件。在这篇博文中,我们将讨论为什么要这样。如果您构建一个类似web服务器的应用程序,那么锁定文件非常有用。但是,如果将库或CLI发布到npm,则永远不要发布锁文件。如果使用锁文件,则意味着您的用户和您可能使用不同版本的依赖项。一个锁文件描述了整个依

调试程序时遇到的最常见情景之一可能是“在我的电脑上明明是好的”。这通常是由于对程序带有bug和自己系统的底层依赖不同的结果。 因此,yarn和npm在引入了的“lock files”,可以跟踪依赖项的确切版本。但是,当您开发将发布到npm的包时,应避免使用此类锁文件。在这篇博文中,我们将讨论为什么要这样。

如果您构建一个类似web服务器的应用程序,那么锁定文件非常有用。但是,如果将库或CLI发布到npm,则永远不要发布锁文件。如果使用锁文件,则意味着您的用户和您可能使用不同版本的依赖项。

什么是锁文件?

一个锁文件描述了整个依赖树,因为它在创建时被解析,包括与特定版本的嵌套依赖关系。在npm中,这些被称为 package-lock.json 和在yarn中,它们被称为 yarn.lock 。在npm和yarn中,它们都放在package.json旁边。

package-lock.json 看起来像这样:

{
 "name": "lockfile-demo",
 "version": "1.0.0",
 "lockfileVersion": 1,
 "requires": true,
 "dependencies": {
   "ansi-styles": {
     "version": "3.2.1",
     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
     "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
     "requires": {
       "color-convert": "^1.9.0"
     }
   },
   "chalk": {
     "version": "2.4.2",
     "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
     "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
     "requires": {
       "ansi-styles": "^3.2.1",
       "escape-string-regexp": "^1.0.5",
       "supports-color": "^5.3.0"
     }
   }
 }
}
复制代码

yarn.lock 文件格式不同,但包含类似的信息:

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


ansi-styles@^3.2.1:
  version "3.2.1"
  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
  dependencies:
        color-convert "^1.9.0"

chalk@^2.4.2:
  version "2.4.2"
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
  dependencies:
        ansi-styles "^3.2.1"
        escape-string-regexp "^1.0.5"
        supports-color "^5.3.0"
复制代码

这两份文件都记录了一些重要的信息:

  1. 安装的每个依赖项的实际版本
  2. 每个依赖项的依赖项
  3. 已解析的包,包括一个校验和,用于验证包的完整性

因此,如果所有依赖项都列在锁文件中,为什么还要在package.json中列出它们呢?为什么我们需要两个文件?

package.json vs. Lock File

项目“package.json”文件中的 dependencies 字段的目的是显示应该安装的依赖项,而不是这些依赖项的依赖项。依赖项可以指定精确的版本或在Semver版本号范围内。对于使用semver版本号规则的,npm或yarn将选择最适合安装的版本。

这意味着,如果在发布新版本期间运行两次 npm install ,那么实际上可能得到不同依赖项的版本。例如,如果您使用 npm install twilio 安装一个叫 twilio 的依赖项。json可能有一个类似的条目:

{
  "dependencies": {
     "twilio": "^3.30.3"
  }
}
复制代码

如果你在npm页面上查看semver的文档,你会发现 ^ 实际上意味着任何大于3.30.3和小于4.0.0的版本都是有效的。因此,如果任何新版本发布,而你没有一个锁文件存在,npm或yarn将安装那个新的版本并不会自动更新 package.json 。然而,如果存在锁文件就不会这样子。

如果npm或yarn找到各自的锁文件,它们将使用这些文件进行模块安装。这对于在需要确保测试在可预测环境中运行的平台上进行持续集成(CI)之类的情况特别有用。对于这个用例,您可以使用特殊的命令或标志与相应的包管理器:

npm ci # 将确切地安装package-lock.json中的内容
yarn install --frozen-lock-file # 将准确地安装yarn.lock中的内容。不更新锁定
复制代码

这在构建web应用程序或服务器之类的应用程序时非常有用,因为在CI环境中,我们希望模拟用户的行为。因此,如果我们开始在源代码控制中跟踪锁文件(如git),我们可以确保每个开发人员、服务器、构建系统和CI系统使用相同版本的依赖。

那么,当我们编写库或其他打算发布到npm仓库的东西时,为什么不希望做同样的事情呢?为了回答这个问题,我们首先要谈谈发包是如何运作的。

如何发布模块

与一些人一般认知不同,发布到npm的内容并不总是与GitHub上的内容相同,也不总是与项目中的总体内容相同。模块发布的方式是,npm将通过检查 package.json 文件中的 files 配置和 .npmignore 文件来确定应该发布的文件。如果没有 .npmignore 文件则使用 .gitignore 文件。还有一些文件总是包含在其中,而另一些文件总是被排除在外。您可以在npm页面上找到这些文件的完整列表。例如, .git 文件夹总是会被忽略。

之后,npm将获取文件列表,并使用 npm pack 将它们打包成一个 tarball 。如果你想查看哪些文件被打包,你可以运行 npm pack --dry-run 命令,它将输出与所有文件:

什么时候我们不应该使用锁文件

然后,该 tarball 将被上传到npm包仓库。运行此命令时,您可能注意到了, package-lock.json 并没有被打入包中。这是因为 package-lock.json 总是会被忽略,正如npm文档中的列表所指定的那样。

这意味着如果其他开发人员安装了你发布的包,他们将永远不会下载你的 package-lock.json 。因此,在安装期间将完全不受锁文件影响。

这可能会意外地导致“在我的机器明明是好的”的效果,因为您的CI和开发人员环境可能会获得不同版本的依赖关系。那么我们应该做些什么呢?

禁用锁定文件和Shrinkwrapping文件

首先,我们应该确保停止跟踪锁定文件。如果您正在使用git,请将以下内容添加到项目中的 .gitignore 文件中:

yarn.lock
package-lock.json
复制代码

yarn官方文档说即使是你写的库,也应该登记一份 yarn.lock 文件。但是,如果你想确保拥有与用户相同的体验,我建议将 yarn.lock 添加到 .gitignore

您可以关闭 package-lock.json 文件的生成。通过在项目中创建或将以下内容添加到.npmrc文件

package-lock = false
复制代码

对于 yarn ,您可以使用 yarn install --no-lockfile 命令不生成锁定文件。

然而,不是说因为我们不使用 package-lock.json 文件就没有办法锁定依赖项和子依赖项。我们还可以使用另一个名为 npm-shrinkwrap.json 的文件。

它基本上与 package-lock.json 相同。由 npm shrinkwrap 命令生成,并实际打包并发布到npm仓库。

因此,通过将 npm shrinkwrap 作为预打包脚本甚至git提交钩子添加到npm脚本中,您可以确保在开发环境、用户和CI中使用相同版本的依赖关系。

有一点很重要,一定要小心使用。通过使用 shrinkwrap 文件安装依赖包,你可以锁定准确的版本,这可能很棒,但它也可以阻止人们获得关键补丁。npm强烈反对对库使用 shrinkwrap ,并建议只在CLIs或类似的场景使用 shrinkwrap

怎样才能得到更多信息

虽然在npm文档中有很多关于这方面的资料,但有时很难找到。如果您想更好地了解要安装或打包的内容,一个常见的命令就是 --dry-run 。运行该命令不影响应用。例如 npm install --dry-run 实际上不会将依赖项安装到项目目录, npm publish --dry-run 实际上不会发布包。

下面是一些你可能想要查看的命令:

npm ci --dry-run # 基于package-lock.json 或者 npm-shrinkwrap.json文件模拟安装
npm pack --dry-run # 列出了所有要打包的文件以及元信息
npm install <dep> --verbose --dry-run # 将以verbose模式运行包的安装,而无需实际将其安装到文件系统
复制代码

有关该主题的一些有用的文档链接如下:

这在很大程度上取决于npm如何处理打包、发布和安装依赖项,而且随着不断变化的环境,这一点可能会在某一时刻发生变化。我希望这篇文章能让你对这个复杂的话题有更多的了解。

原文: When Not to Use Lock Files with Node.js


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图解网络硬件

图解网络硬件

[日] 三轮贤一 / 盛荣 / 人民邮电出版社 / 2014-7 / 69.00元

本书详细介绍了计算机网络硬件的相关知识,在对硬件设备、相关技术及规范进行详尽考据和整理的同时,侧重工程实践,重点讲述了在实际网络建设工程中真实使用的网络硬件设备及其相关背景知识,能够帮助读者深入理解计算机网络在工程实践中某些容易混淆的概念,如L3交换机和路由器等。 本书在讲解的同时,还辅以丰富的图例,使计算机网络设备的真实情况一目了然,同时深入浅出地介绍了原本复杂抽象的计算机网络术语,因此对......一起来看看 《图解网络硬件》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换