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

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

内容简介:调试程序时遇到的最常见情景之一可能是“在我的电脑上明明是好的”。这通常是由于对程序带有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


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

查看所有标签

猜你喜欢:

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

Grails权威指南

Grails权威指南

瑞切 / 张若飞 / 电子工业 / 2007-11 / 49.80元

《Grails权威指南》译自由Grails项目负责人Graeme Keith Rocher编写的《The Definitive Guide to Grails》,着重介绍了如何在Grails框架下使用Groovy语言进行敏捷的Web开发。本书详细讲解Grails开发的全部过程,包括项目构架、控制器与视图、与关系数据库之间的ORM映射,以及与Ajax和Java平台的无缝集成。同时该书也揭示了Grai......一起来看看 《Grails权威指南》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具