内容简介:调试程序时遇到的最常见情景之一可能是“在我的电脑上明明是好的”。这通常是由于对程序带有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" 复制代码
这两份文件都记录了一些重要的信息:
- 安装的每个依赖项的实际版本
- 每个依赖项的依赖项
- 已解析的包,包括一个校验和,用于验证包的完整性
因此,如果所有依赖项都列在锁文件中,为什么还要在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如何处理打包、发布和安装依赖项,而且随着不断变化的环境,这一点可能会在某一时刻发生变化。我希望这篇文章能让你对这个复杂的话题有更多的了解。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 企业什么时候不应该采用敏捷开发(Agile)?
- 什么时候应该在ES6中使用箭头函数?
- 该崩溃的时候就崩溃吧,至少写程序应该是这样
- 是时候谈谈JavaScript面向对象了!(我们什么时候更需要它)
- LWN:写文件的时候不希望写入一半的时候掉电丢失,怎么办?
- .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Grails权威指南
瑞切 / 张若飞 / 电子工业 / 2007-11 / 49.80元
《Grails权威指南》译自由Grails项目负责人Graeme Keith Rocher编写的《The Definitive Guide to Grails》,着重介绍了如何在Grails框架下使用Groovy语言进行敏捷的Web开发。本书详细讲解Grails开发的全部过程,包括项目构架、控制器与视图、与关系数据库之间的ORM映射,以及与Ajax和Java平台的无缝集成。同时该书也揭示了Grai......一起来看看 《Grails权威指南》 这本书的介绍吧!