跳到主要内容
pnpm
文档目录

package.json

查看英文原文 ↗

包的清单文件。它包含包的所有元数据,包括依赖、标题、作者等。这是包括 pnpm 在内的所有主流 Node.js 包管理器共同遵循的标准。

除传统的 package.json 格式外,pnpm 还支持 package.json5(通过 json5)和 package.yaml(通过 js-yaml)。

engines

你可以指定软件运行所需的 Node 和 pnpm 版本:

{
    "engines": {
        "node": ">=10",
        "pnpm": ">=3"
    }
}

本地开发期间,如果 pnpm 自身版本与 engines 字段指定的不匹配,pnpm 将始终报错失败。

除非用户设置了 engineStrict 配置标志(参见 settings),否则此字段仅供参考,仅在你的包作为依赖被安装时产生警告。

engines.runtime

自 v10.21.0 起提供

指定依赖所需的 Node.js 运行时。声明后,pnpm 会自动安装指定的 Node.js 版本。

{
  "engines": {
    "runtime": {
      "name": "node",
      "version": "^24.11.0",
      "onFail": "download"
    }
  }
}

当包声明了运行时:

  1. 对于 CLI 应用:pnpm 把 CLI 绑定到所需的 Node.js 版本,确保无论全局安装的 Node.js 是哪个实例,都使用正确的运行时。
  2. 对于带 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"
      }
    ]
  }
}

工作原理:

  1. pnpm install 会将你指定的范围解析为匹配的最新运行时版本。
  2. 精确版本(及校验和)保存在锁文件中。
  3. 脚本使用本地运行时,确保跨环境的一致性。

要在不修改清单的情况下覆盖声明的 onFail 行为,使用 runtimeOnFail 设置。

自 v12.0.0-rc.2 起,在项目内直接运行 node(或 deno/bun)也会遵循此锁定版本,而不仅是脚本。可通过 globalShims 设置关闭,或用 PNPM_SHIM_BYPASS=1 对单条命令跳过。参见项目感知的全局命令

devEngines.packageManager

自 v11.0.0 起提供

允许通过 package.json 中的 devEngines.packageManager 指定 pnpm 版本。与 packageManager 字段不同,它支持版本范围。解析出的版本会记录在 pnpm-lock.yamlpackageManagerDependencies 下,若仍满足范围则会被复用。

{
  "devEngines": {
    "packageManager": {
      "name": "pnpm",
      "version": ">=12.0.0 <13.0.0",
      "onFail": "download"
    }
  }
}

自 v12.0.0-rc.6 起,该字段还可以指定其他包管理器,即 npmyarnbunpnpm add npm@11 写入的就是这种形式。对于这些管理器,pnpm-lock.yaml 中不会记录任何内容:packageManagerDependencies 保存的是 pnpm 自身的锁定,其他包管理器则锁定在 pnpm 主目录下各自的环境锁文件中。

要在不修改清单的情况下覆盖 onFail 行为,参见 pmOnFail 设置。

dependenciesMeta

用于 dependenciesoptionalDependenciesdevDependencies 中声明的依赖的附加元信息。

dependenciesMeta.*.injected

如果某个依赖是本地工作区包,且此项设为 true,安装该包时会在虚拟存储(node_modules/.pnpm)中创建其硬链接副本。

如果此项设为 false 或未设置,则改为在 node_modules 中创建符号链接来安装该依赖,链接指向包在工作区中的源码目录。这是默认行为,速度更快,且对依赖的任何修改都会立即对其使用者可见。

例如,假设以下 package.json 是一个本地工作区包:

{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0"
  }
}

button 依赖通常这样安装:在 cardnode_modules 目录中创建一个符号链接,指向 button 的开发目录。

但如果 button 在其 peerDependencies 中声明了 react 呢?如果 monorepo(单体仓库)中所有项目都使用同一版本的 react,就没有问题。但假如 button 同时被使用 react@16card 和使用 react@17form 需要呢?通常你只能选定单一版本的 react,并通过 buttondevDependencies 指定它。符号链接无法让 cardform 等不同使用者以不同方式满足 react 这一对等依赖。

injected 字段通过向虚拟存储安装 button 的硬链接副本解决这一问题。为此,cardpackage.json 可配置如下:

{
  "name": "card",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "16"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}

formpackage.json 可配置如下:

{
  "name": "form",
  "dependencies": {
    "button": "workspace:1.0.0",
    "react": "17"
  },
  "dependenciesMeta": {
    "button": {
      "injected": true
    }
  }
}

有了这些更改,可以说 buttoncardform 的「注入依赖」。当 button 导入 react 时,在 card 的上下文中解析为 react@16,在 form 的上下文中则解析为 react@17

由于注入依赖会生成其工作区源码目录的副本,因此代码一旦修改,就必须以某种方式更新这些副本,否则使用者看不到新的状态。使用 pnpm --recursive run build 这类命令构建多个项目时,该更新必须发生在每个被注入包重新构建之后、其使用者重新构建之前。对于简单场景,可以再执行一次 pnpm install 来完成,例如借助 package.json 的生命周期脚本(如 "prepare": "pnpm run build")重新构建该项目。pnpm-syncpnpm-sync-dependencies-meta-injected 等第三方工具为更新注入依赖提供了更稳健高效的方案,并支持监听模式。

peerDependencies

对等依赖的值通常是 semver 范围(^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 说明符(<registry>:<version>)、npm: 别名,以及 file:、git 或 URL 说明符。

这类说明符会与其携带的 semver 范围匹配:work:5.x.x5.x.x 检查,npm:other-lib@^5^5 检查。不带版本的说明符(如 file:../lib-c)按 * 匹配,因此任何版本都满足。同时,当 autoInstallPeers 安装缺失的对等依赖时,由原始说明符负责选择包,因此该对等依赖会从你指定的别名、registry 或来源拉取。

裸的 name@version 值仍会以 ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION 被拒绝,因为它们几乎总是笔误:

{
  "peerDependencies": {
    "lib-a": "lib-a@1.2.3"
  }
}

peerDependenciesMeta

此字段列出与 peerDependencies 字段中所列依赖相关的一些附加信息。

peerDependenciesMeta.*.optional

如果设为 true,所选对等依赖会被包管理器标记为可选,因此使用者未提供它不再被报告为错误。

例如:

{
    "peerDependencies": {
        "foo": "1"
    },
    "peerDependenciesMeta": {
        "foo": {
            "optional": true
        },
        "bar": {
            "optional": true
        }
    }
}

注意,尽管 bar 未在 peerDependencies 中声明,它也被标记为可选。因此 pnpm 认为 bar 的任何版本都可以。而 foo 是可选的,但仅限于其要求的版本规范。

publishConfig

在包被打包之前,可以覆盖清单中的某些字段。可覆盖的字段有:

要覆盖某个字段,把发布时使用的该字段值加入 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"
  }
}

只有发布产物会被改名:依赖方、pnpm-lock.yaml 和发布工具仍按清单名寻址该项目。新名称会进入打包后的清单、tarball 文件名,以及一切在 registry 上寻址该包的环节:pnpm publish -r 的已发布检查及其 registry 选择,还有 pnpm change statuspnpm 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
  • 类型:布尔值

设为 true 时,本地开发期间会从 publishConfig.directory 位置对该项目进行符号链接。

例如:

{
  "name": "foo",
  "version": "1.0.0",
  "publishConfig": {
    "directory": "dist",
    "linkDirectory": true
  }
}

本页内容译自pnpm 官方文档(MIT License),如有出入以英文原文为准。