hello,我是海海
这一期是关于锁文件的一篇译作。阅读时间6分钟
欢迎转载,请注明原文和作者
翻译的不够好,欢迎底部发消息帮我纠错
原标题:What is package lock json and how a lockfile works for yarn and npm packages?
原作者:Liran Tal
本文大纲:
- 什么是锁文件?
- 为什么需要锁文件?
- 锁文件的工作原理?
- 特殊锁文件:
npm-shrinkwrap.json
package.json
和锁文件不同时,会怎样?- 构建应用程序或者第三方库时,该如何处理锁文件?
什么是锁文件?
在本文中,我们主要讨论npm
的锁文件package-lock.json
和Yarn
的锁文件yarn.lock
。作为开发项目的依赖清单,它可以指定项目的依赖版本和依赖的依赖版本,从而构建整个依赖树。
当安装依赖时,锁文件会首先被引入到项目中。锁文件会计算项目的依赖关系树并将其保存,其中包括了每个依赖关系的元数据。
这些元数据包括:
version
:包版本integrity
:防止篡改的完整性哈希resolved
:包源地址
为什么需要锁文件?
锁文件能够在被创建时确定项目的整个依赖关系树的所有版本。
如果没有包锁定文件,Yarn
或npm
等包管理器将在包的依赖项安装过程中实时解析包的最新版本,而不是最初用于特定包的版本,这可能会造成问题。
举个例子,如果一个项目依赖于包dummy-pkg:^1.0.0
,那么在不同时间执行的两个单独的安装可能会检索不同版本的dummy-pkg
。如果A用户安装时版本为1.0.0,然后该包在几分钟后发布新版本1.0.1,B用户此时安装的版本会是1.0.1,而不是1.0.0。
锁文件的工作原理?
大多数npm
生态可以识别两种包锁定文件:
yarn.lock
package-lock.json
没有什么比一个好的流程图更能解释这两者的使用了。
上图中使用了npm
的package-lock.json
,但可以在任何地方用yarn.lock
代替。唯一的例外是npm
客户端发布过程中不会自动忽略yarn.lock文件(会自动忽略package-lock.json) 。因此,除非在.npmignore
文件中明确忽略,否则它将包含在打包的tarball
中。但是,正如我们在插图左侧看到的那样,即使该包锁定文件作为包的一部分存在,它也不会供使用该库的最终用户使用。
Yarn
和npm
都不会考虑在node_modules
包中的锁文件(原文是transient dependencies),它们会被包管理器完全忽略。只有根目录的下的锁文件才有效。
特殊锁文件:npm-shrinkwrap.json
存在一个特殊的锁文件,即使对于node_modules
中包的锁文件的依赖关系也会考虑该文件。这个文件是npm-shrinkwrap.json
。
这个文件不仅像yarn.lock
,package-lock.json
一样能够固定依赖关系树,而且在发包时会被提交而不会像package-lock.json
被忽略。
更重要的是,用户在运行npm install
安装某包时,版本的选择权被控制在npm-shrinkwrap.json
而不是package-lock.json
。
此外,需要注意的是,yarn
和npm
对于npm-shrinkwrap.json
的处理方式也是不同的:
npm
始终会将npm-shrinkwrap.json
中的依赖项放入包自己的node_modules
文件夹中,and will not try to flatten it up the tree.(这里翻译不好,可能是不会将其放在项目的依赖树上)yarn
会忽略npm-shrinkwrap.json
npm-shrinkwrap.json
的用处:
- 允许库的维护人员确定并管理自己的库依赖项,以便发布已知版本。虽然需要仔细维护整个依赖树
- 使用该文件时,源代码管理中不需要存在任何其他锁文件。
- 著名的例子,比如hapijs
package.json
和锁文件不同时,会怎样?
开发人员添加或删除依赖项,克隆项目时安装依赖时都会引入锁文件,这些都是常见的做法,但如果他们在package.json
中进行更改并忘记提交相关的锁文件时,会发生什么情况?
当项目的package.json
与其锁文件不同步时,npm
和yarn
等包管理器将尝试协调差异并生成新的依赖目录(mainfest)。虽然这听上去像是一件好事,但如果在CI期间发生这种情况,实际上会引发问题。
如果锁文件和package.json
不同,并且构建时成功,则意味着正在构建或测试的项目可以使用任何版本的依赖,这与我们使用包管理器的目的背道而驰。
因此,建议包管理器在安装依赖时使用锁定文件。例如:
yarn install --frozen-lock file
npm ci
构建应用程序或者第三方库时,该如何处理锁文件?
关于如何使用锁文件的观点各不相同,具体取决于该项目是主应用程序,还是一个工具库。
对于使用锁文件的应用程序已经达成共识,但是作为工具库的项目,却没有,为什么会这样?
但是,如果不适用锁文件,依赖关系仅仅在安装期间确定,且对于维护者和使用者可能会有所不同。
就我个人而言,我认为库项目和应用程序没有什么不同,都应该包含一个锁文件,以便团队成员协作和可重现的构建。
我建议使用两个不同的CI构建来解决这个问题:
- 使用锁文件构建
- 忽略锁文件,只在构建时确定依赖关系
这不仅可以实现重复构建,并保持依赖关系一致,同时使用户可以发现库的任何潜在问题。
感谢你的耐心阅读,如果觉得好的话,可以给我点个赞吗
创作不易,感谢你的支持!
本文使用 markdown.com.cn 排版