package-lock.json

清单的体现

选择命令行版本:

描述

🌐 Description

package-lock.json 会自动生成,用于任何 npm 修改 node_modules 树或 package.json 的操作。它描述了生成的精确树,从而使随后的安装能够生成相同的树结构,无论中间依赖如何更新。

该文件旨在提交到源存储库中,并用于各种目的:

🌐 This file is intended to be committed into source repositories, and serves various purposes:

  • 描述依赖树的单一表示,以保证团队成员、部署和持续集成安装完全相同的依赖。
  • 提供一个功能,让用户可以“时光旅行”到 node_modules 的先前状态,而无需提交目录本身。
  • 通过可读的源代码控制差异促进树变化的更大可见性。
  • 通过允许 npm 跳过以前安装的包的重复元数据解析来优化安装过程。
  • 从 npm v7 开始,锁定文件包含了足够的信息来完整了解包树,从而减少了读取 package.json 文件的需求,并且可以显著提升性能。

npm 创建或更新 package-lock.json 时,它会从 package.json 推断行结束符和缩进,以使两个文件的格式保持一致。

🌐 When npm creates or updates package-lock.json, it will infer line endings and indentation from package.json so that the formatting of both files matches.

package-lock.json 对比 npm-shrinkwrap.json

🌐 package-lock.json vs npm-shrinkwrap.json

这两个文件具有相同的格式,并且在项目的根目录中执行类似的功能。

🌐 Both of these files have the same format, and perform similar functions in the root of a project.

区别在于 package-lock.json 无法发布,如果在根项目以外的任何地方出现,它将被忽略。

🌐 The difference is that package-lock.json cannot be published, and it will be ignored if found in any place other than the root project.

相比之下,npm-shrinkwrap.json 允许发布,并定义从遇到的点开始的依赖树。除非部署 CLI 工具或以发布流程生成生产包,否则不推荐使用。

🌐 In contrast, npm-shrinkwrap.json allows publication, and defines the dependency tree from the point encountered. This is not recommended unless deploying a CLI tool or otherwise using the publication process for producing production packages.

如果在项目根目录中同时存在 package-lock.jsonnpm-shrinkwrap.jsonnpm-shrinkwrap.json 将优先,package-lock.json 将被忽略。

🌐 If both package-lock.json and npm-shrinkwrap.json are present in the root of a project, npm-shrinkwrap.json will take precedence and package-lock.json will be ignored.

隐藏的锁文件

🌐 Hidden Lockfiles

为了避免重复处理 node_modules 文件夹,从 npm v7 开始使用存在于 node_modules/.package-lock.json 中的“隐藏”锁文件。它包含关于依赖树的信息,并且在满足以下条件的情况下,可以用它来代替读取整个 node_modules 层级结构:

🌐 In order to avoid processing the node_modules folder repeatedly, npm as of v7 uses a "hidden" lockfile present in node_modules/.package-lock.json. This contains information about the tree, and is used in lieu of reading the entire node_modules hierarchy provided that the following conditions are met:

  • 它引用的所有软件包文件夹都存在于 node_modules 层级结构中。
  • node_modules 层级中不存在未在锁定文件中列出的包文件夹。
  • 文件的修改时间至少与它引用的所有包文件夹一样新。

也就是说,隐藏的锁定文件只有在作为最近一次包树更新的一部分创建时才相关。如果其他 CLI 以任何方式更改了包树,这将被检测到,并且隐藏的锁定文件将被忽略。

🌐 That is, the hidden lockfile will only be relevant if it was created as part of the most recent update to the package tree. If another CLI mutates the tree in any way, this will be detected, and the hidden lockfile will be ignored.

请注意,确实可以以一种方式手动更改包的内容,而不会影响包文件夹的修改时间。例如,如果你向 node_modules/foo/lib/bar.js 添加文件,那么 node_modules/foo 的修改时间将不会反映此更改。如果你正在手动编辑 node_modules 中的文件,通常最好删除 node_modules/.package-lock.json 中的文件。

🌐 Note that it is possible to manually change the contents of a package in such a way that the modified time of the package folder is unaffected. For example, if you add a file to node_modules/foo/lib/bar.js, then the modified time on node_modules/foo will not reflect this change. If you are manually editing files in node_modules, it is generally best to delete the file at node_modules/.package-lock.json.

由于隐藏的 lockfile 会被旧版本的 npm 忽略,它不包含“普通” lockfile 中存在的向后兼容功能。也就是说,它是 lockfileVersion: 3,而不是 lockfileVersion: 2

🌐 As the hidden lockfile is ignored by older npm versions, it does not contain the backwards compatibility affordances present in "normal" lockfiles. That is, it is lockfileVersion: 3, rather than lockfileVersion: 2.

处理旧的锁文件

🌐 Handling Old Lockfiles

当 npm 在安装包的过程中检测到来自 npm v6 或更早版本的锁定文件时,它会自动更新,以从 node_modules 树中获取缺失的信息,或者(在空的 node_modules 树或非常旧的锁定文件格式的情况下)从 npm 注册表中获取。

🌐 When npm detects a lockfile from npm v6 or before during the package installation process, it is automatically updated to fetch missing information from either the node_modules tree or (in the case of empty node_modules trees or very old lockfile formats) the npm registry.

文件格式

🌐 File Format

name

这是一个包锁文件所对应的包的名称。这将与 package.json 中的内容匹配。

🌐 The name of the package this is a package-lock for. This will match what's in package.json.

version

这是该软件包的 package-lock 所对应的软件包版本。这将与 package.json 中的内容匹配。

🌐 The version of the package this is a package-lock for. This will match what's in package.json.

lockfileVersion

一个整数版本,从 1 开始,表示在生成此 package-lock.json 时使用的本文档的版本号。

🌐 An integer version, starting at 1 with the version number of this document whose semantics were used when generating this package-lock.json.

请注意,在 npm v7 中,文件格式发生了显著变化,以跟踪原本需要查看 node_modules 或 npm 注册表的信息。由 npm v7 生成的锁文件将包含 lockfileVersion: 2

🌐 Note that the file format changed significantly in npm v7 to track information that would have otherwise required looking in node_modules or the npm registry. Lockfiles generated by npm v7 will contain lockfileVersion: 2.

  • 未提供版本:这是一个“古老”的 shrinkwrap 文件,来自 npm v5 之前的 npm 版本。
  • 1:npm v5 和 v6 使用的 lockfile 版本。
  • 2:npm v7 和 v8 使用的锁文件版本。向后兼容 v1 锁文件。
  • 3:npm v9 及以上版本使用的锁文件版本。向后兼容 npm v7。

npm 将始终尝试从锁定文件中获取任何数据,即使它不是它旨在支持的版本。

🌐 npm will always attempt to get whatever data it can out of a lockfile, even if it is not a version that it was designed to support.

packages

这是一个将包位置映射到包含该包信息的对象的对象。

🌐 This is an object that maps package locations to an object containing the information about that package.

根项目通常以 "" 作为键列出,所有其他包则以相对于根项目文件夹的路径列出。

🌐 The root project is typically listed with a key of "", and all other packages are listed with their relative paths from the root project folder.

包描述符具有以下字段:

🌐 Package descriptors have the following fields:

  • 版本:在 package.json 中找到的版本
  • 解析自:包实际解析来源的地方。对于从注册表获取的包,这将是一个指向 tar 包的 URL。对于 git 依赖,这将是包含提交 SHA 的完整 git URL。对于链接依赖,这将是链接目标的位置。registry.npmjs.org 是一个表示“当前配置的注册表”的魔法值。
  • 完整性:此位置解包的工件的 sha512sha1 标准子资源完整性 字符串。
  • link:用于指示这是一个符号链接的标志。如果存在此项,则不会指定其他字段,因为链接目标也将包含在锁定文件中。
  • dev、optional、devOptional:如果该软件包严格属于 devDependencies 树,则 dev 将为真。如果它严格属于 optionalDependencies 树,则会设置 optional。如果它既是 dev 的依赖又是非开发依赖的 optional 依赖,则会设置 devOptional。(dev 依赖的 optional 依赖将同时设置 devoptional。)
  • inBundle:一个标志,用于表示该包是打包依赖。
  • hasInstallScript:一个标志,用于表示该包有 preinstallinstallpostinstall 脚本。
  • hasShrinkwrap:一个标志,用于指示该包是否有 npm-shrinkwrap.json 文件。
  • bin、license、engines、dependencies、optionalDependencies:来自 package.json 的字段

dependencies

用于支持使用 lockfileVersion: 1 的 npm 版本的遗留数据。这是一个将包名称映射到依赖对象的映射。由于对象结构是严格分层的,因此在某些情况下表示符号链接依赖有些困难。

🌐 Legacy data for supporting versions of npm that use lockfileVersion: 1. This is a mapping of package names to dependency objects. Because the object structure is strictly hierarchical, symbolic link dependencies are somewhat challenging to represent in some cases.

如果存在 packages 部分,npm v7 将完全忽略本节,但会保持其更新,以支持在 npm v6 和 npm v7 之间切换。

🌐 npm v7 ignores this section entirely if a packages section is present, but does keep it up to date in order to support switching between npm v6 and npm v7.

依赖对象具有以下字段:

🌐 Dependency objects have the following fields:

  • 版本:一个根据包的性质而变化的指定符,可用于获取该包的新副本。
    • 打包依赖:无论来源如何,这只是一个纯粹用于信息参考的版本号。
    • 注册表来源:这是一个版本号。(例如,1.2.3
    • git 来源:这是一个带有已解析提交标识的 git 指定符。(例如,git+https://example.com/foo/bar#115311855adb0789a0466714ed48a1499ffea97e)
    • http 压缩包来源:这是压缩包的 URL。(例如,https://example.com/example-1.3.0.tgz
    • 本地 tar 包来源:这是 tar 包的文件 URL。(例如 file:///opt/storage/example-1.3.0.tgz
    • 本地链接来源:这是链接的文件 URL。(例如 file:libs/our-module
  • 完整性:位于此位置解压的工件的 sha512sha1 标准子资源完整性 字符串。对于 git 依赖,这是提交的 sha 值。
  • 已解决:对于注册表源,这是相对于注册表 URL 的 tar 包路径。如果 tar 包 URL 不在与注册表 URL 相同的服务器上,则这是一个完整的 URL。registry.npmjs.org 是一个魔法值,表示“当前配置的注册表”。
  • 打包:如果为真,则这是打包的依赖,将由父模块安装。在安装时,本模块将在提取阶段从父模块中提取,而不是作为单独的依赖安装。
  • dev:如果为真,则此依赖仅是顶层模块的开发依赖或其传递依赖。对于既是顶层的开发依赖又是顶层非开发依赖的传递依赖的依赖,该值为假。
  • 可选:如果为 true,则此依赖要么只是顶层模块的可选依赖,要么是其传递依赖。对于既是顶层模块的可选依赖又是顶层模块非可选依赖的传递依赖的依赖,该值为 false。
  • 要求:这是模块名称到版本的映射。这是该模块所需的所有内容的列表,无论它将安装在哪里。版本应通过正常的匹配规则与我们的 dependencies 中的依赖或比我们级别更高的依赖匹配。
  • 依赖:此依赖的依赖,与顶层的完全相同。

也可以看看

🌐 See also