package.json
一个包的清单文件。它包含包的所有元数据,包括依赖项、标题、作者等等。这是所有主要的 Node.js 包管理工具,包括 pnpm 的保留标准。
除了传统的 package.json 格式之外,pnpm 还支持 package.json5 (通过 json5)和 package.yaml (通过 js-yaml)。
If a directory contains more than one of these files, pnpm uses package.json, then package.json5, then package.yaml. Since v11.28.0, workspace discovery follows the same order and finds one project per directory.
注意
自 v11 版本起,pnpm 不再从 package.json 的 pnpm 字段读取设置。设置必须在 pnpm-workspace.yaml 文件中定义。请参阅 配置。
bin#
The bin field maps command names to files inside the package. pnpm normalizes
backslash separators to / and parent directory segments at the package root. For example,
../dist/cli.js resolves to dist/cli.js inside the package.
engines#
你可以指定你的软件能够运行的 Node 版本和 pnpm 版本:
{
"engines": {
"node": ">=10",
"pnpm": ">=3"
}
}
在本地开发时, 如果其版本与 engines 字段中指定的版本不匹配,pnpm 将始终失败并报错。
除非用户设置了 engineStrict 配置标志(参见 设置),否则此 字段仅供参考,并且仅当您的包作为依赖项安装时才会产生警告。
engines.runtime#
添加于:v10.21.0
指定依赖项所需的 Node.js 运行时环境。当声明时,pnpm 将自动安装指定的 Node.js 版本。
{
"engines": {
"runtime": {
"name": "node",
"version": "^24.11.0",
"onFail": "download"
}
}
}
当一个包声明运行时时:
- 对于 CLI 应用程序:pnpm 将 CLI 绑定到所需的 Node.js 版本,确保无论全局安装的 Node.js 实例如何,它都能使用正确的运行时。
- 对于带有
postinstall脚本的软件包:该脚本使用指定的 Node.js 版本执行。
这对于需要特定 Node.js 版本才能正常运行的依赖项尤其有用。
devEngines.runtime#
添加于:v10.14
允许指定项目使用的一个或多个 JavaScript 运行时引擎。支持的运行时包括 Node.js、Deno 和 Bun。
例如,下面是如何将 node@^24.4.0 添加到你的依赖项中:
{
"devEngines": {
"runtime": {
"name": "node",
"version": "^24.4.0",
"onFail": "download"
}
}
}
你也可以将多个运行时添加到同一个 package.json:
{
"devEngines": {
"runtime": [
{
"name": "node",
"version": "^24.4.0",
"onFail": "download"
},
{
"name": "deno",
"version": "^2.4.3",
"onFail": "download"
}
]
}
}
工作原理:
pnpm install将你指定的范围解析为最新的匹配运行时版本。- 精确的版本(和校验和)保存在锁文件(lockfile)中。
- 脚本使用本地运行时,确保跨环境的一致性。
要覆盖声明的 onFail 行为而不编辑清单,请使用 runtimeOnFail 设置。
devEngines.packageManager#
添加于:v11.0.0
允许通过 package.json 中的 devEngines.packageManager 指定 pnpm 版本。与 packageManager 字段不同,此字段支持版本范围。解析后的版本存储在 packageManagerDependencies 下的 pnpm-lock.yaml 中,如果仍然满足范围,则会被重用。
When the lockfile records no version yet, pnpm records the running pnpm if it satisfies the range and was published at least minimumReleaseAge ago. Otherwise pnpm records the newest version in the range that is old enough. If no version in the range is old enough, pnpm records the running pnpm.
{
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": ">=11.0.0 <12.0.0",
"onFail": "download"
}
}
}
注意
When pnpm is declared via the legacy packageManager field (not devEngines.packageManager), its resolution info is not written to pnpm-lock.yaml. Use devEngines.packageManager when the resolved version should be recorded in the lockfile.
要覆盖 onFail 行为而不编辑清单,请参阅 pmOnFail 设置。
dependenciesMeta#
用于在 dependencies, optionalDependencies 和 devDependencies 中声明的依赖项的补充元信息。
dependenciesMeta.*.injected#
如果将本地工作区包依赖项设置为 true,则将通过在虚拟存储中创建硬链接副本来安装该包(node_modules/.pnpm)。
如果将其设置为 false 或未设置,则将通过创建指向工作空间中包的源目录的 node_modules 符号链接来安装依赖项。这是缺省值,因为它更快,并确保对依赖关系的任何修改都将立即对其使用者可视。
例如,假设以下 package.json 是一个本地工作区包:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0"
}
}
button 依赖项通常会通过在 card 的 node_modules 目录中创建符号链接来安装,该符号链接指向 button 的开发目录。
但是,如果 button 在其 peerDependencies 中指定 react,该怎么办?如果 monorepo 中的所有项目都使用相同版本的 react,那么就没有问题。但如果 card 依赖的 button 使用 react@16 并且 form 使用 react@17 呢?通常你必须选择一个版本的 react 并使用 button 的 devDependencies 来指定它。符号链接无法为 react 对等依赖提供一种方式,使不同的消费者(例如 card 和 form)能够以不同的方式满足它。
injected 字段通过在虚拟存储中安装 button 的硬链接副本解决了这个问题。为了实现这一点, card 的 package.json 可以按如下方式配置:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0",
"react": "16"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
而 form 的 package.json 可以按如下方式配置:
{
"name": "form",
"dependencies": {
"button": "workspace:1.0.0",
"react": "17"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
通过这些变化,我们说 button 是 card 和 form 的“注入依赖项”。当 button 导入react 时,它将在 card 的上下文中解析为 react@16,但在 form 的上下文中解析为 react@17。
由于注入依赖关系会生成其工作空间源目录的副本,因此每当修改代码时,都必须更新这些副本; 否则,新状态将不会反映给使用者。当使用命令(例如 pnpm --recursive run build)构建多个项目时,此更新必须在重建每个注入的包之后但重建其使用者之前进行。对于简单的用例,可以通过再次调用 pnpm install 来完成,也许是使用 package.json 生命周期脚本(如 "prepare": "pnpm run build")来重建该项目。 Third party tools such as pnpm-sync and pnpm-sync-dependencies-meta-injected provide a more efficient solution for updating injected dependencies, as well as watch mode support.
peerDependencies#
对等依赖的值通常是语义范围(如 ^1.0.0),或者是 workspace: 或 catalog: 指定符。
自 v11.14.0 版本起,对等依赖也可以使用带有协议前缀的标识符进行声明:
{
"peerDependencies": {
"lib-a": "work:5.x.x",
"lib-b": "npm:other-lib@^5",
"lib-c": "file:../lib-c",
"lib-d": "git+https://example.com/lib-d.git"
}
}
支持的格式包括 命名注册源 指定符(<registry>:<version>)、npm: 别名,以及 file:、git 或 URL 指定符。
Such a specifier is matched against the semver range it carries: work:5.x.x is checked as 5.x.x and npm:other-lib@^5 as ^5. 不包含版本信息的指定符(例如 file:../lib-c)会与 * 匹配,因此任何版本均满足该条件。与此同时,当 autoInstallPeers 安装缺失的对等依赖时,正是最初指定的标识符决定了要安装哪个包;因此,该对等依赖会根据你指定的别名、注册源或来源来进行获取。
仅包含 name@version 的值仍会被 ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION 错误拒绝,因为这几乎总是错误的:
{
"peerDependencies": {
"lib-a": "lib-a@1.2.3"
}
}
peerDependenciesMeta#
此字段列出了一些与 peerDependencies 字段中列出的依赖关系相关的额外信息。
peerDependenciesMeta.*.optional#
如果设置为 true,所选的 peer dependency 将被包管理工具标记为可选的。因此,消费方省略它将不再被报告为错误。
例如:
{
"peerDependencies": {
"foo": "1"
},
"peerDependenciesMeta": {
"foo": {
"optional": true
},
"bar": {
"optional": true
}
}
}
Even though bar was not specified in peerDependencies, it is
marked as optional. 因此,pnpm 将假定任何版本的 bar 都是被允许的。但是,foo 是可选的,但只能使用指定的版本。
publishConfig#
在包被打包之前,可以覆盖清单中的某些字段。以下字段可以被覆盖:
binmainexportstypes或typingsmodulebrowseresnextes2015unpkgumd:maintypesVersions- cpu
- os
engines(添加于 v10.22.0)name(添加于 v11.18.0)
要覆盖字段,请将该字段的发布版本添加到 publishConfig。
例如,以下 package.json:
{
"name": "foo",
"version": "1.0.0",
"main": "src/index.ts",
"publishConfig": {
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
}
将被发布为:
{
"name": "foo",
"version": "1.0.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
publishConfig.name#
添加于:v11.18.0
以不同于其清单在工作区中所用名称的另一个名称发布该包。适用于发布名称已被同级项目占用的项目,否则就只能在发布前的构建步骤中临时改名。
{
"name": "foo-v2",
"version": "2.0.0",
"publishConfig": {
"name": "foo"
}
}
Only the published artifact is renamed. Dependents, pnpm-lock.yaml, and release tooling keep addressing the project by its manifest name. 新名称会体现在打包后的清单、tarball 文件名,以及注册源中所有引用该包的地方:pnpm publish -r 的已发布检查、其注册源选择,以及 pnpm change status 与 pnpm version -r 的发布规划探测。
publishConfig.executableFiles#
默认情况下,出于可移植性的原因,除了 bin 字段中列出的文件之外,不会在生成的包存档中将任何文件标记为可执行文件。 executableFiles 字段允许您声明必须设置可执行标志 (+x) 的额外字段,即使它们不能通过 bin 字段直接访问。
{
"publishConfig": {
"executableFiles": [
"./dist/shim.js"
]
}
}
publishConfig.directory#
你还可以使用 publishConfig.directory 字段来自定义相对于当前 package.json 的发布子目录。
预计在指定目录中有当前包的修改版本(通常使用第三方构建工具)。
在这个例子中
"dist"文件夹必须包含一个package.json
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
}
}
publishConfig.linkDirectory#
- 默认值:true
- 类型:Boolean
当设置为 true 时,项目将在本地开发期间从 publishConfig.directory 位置进行符号链接。
例如:
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist",
"linkDirectory": true
}
}