package.json
包的清单文件。它包含包的所有元数据,包括依赖、标题、作者等。这是所有主要 Node.js 包管理器(包括 pnpm)中保留的标准。
¥The manifest file of a package. It contains all the package's metadata, including dependencies, title, author, et cetera. This is a standard preserved across all major Node.js package managers, including pnpm.
除了传统的 package.json
格式外,pnpm 还支持 package.json5
(通过 json5)和 package.yaml
(通过 js-yaml)。
¥In addition to the traditional package.json
format, pnpm also supports package.json5
(via json5) and package.yaml
(via js-yaml).
engines
你可以指定你的软件运行的 Node 和 pnpm 版本:
¥You can specify the version of Node and pnpm that your software works on:
{
"engines": {
"node": ">=10",
"pnpm": ">=3"
}
}
在本地开发期间,如果 pnpm 的版本与 engines
字段中指定的版本不匹配,则它将始终失败并显示错误消息。
¥During local development, pnpm will always fail with an error message
if its version does not match the one specified in the engines
field.
除非用户设置了 engineStrict
配置标志(参见 settings),否则此字段仅供参考,并且仅在你的包作为依赖安装时才会产生警告。
¥Unless the user has set the engineStrict
config flag (see settings), this
field is advisory only and will only produce warnings when your package is
installed as a dependency.
dependenciesMeta
用于在 dependencies
、optionalDependencies
和 devDependencies
中声明的依赖的附加元信息。
¥Additional meta information used for dependencies declared inside dependencies
, optionalDependencies
, and devDependencies
.
dependencyMeta.*.injected
如果将依赖设置为本地工作区包的 true
,则将通过在虚拟存储 (node_modules/.pnpm
) 中创建硬链接副本来安装该包。
¥If this is set to true
for a dependency that is a local workspace package, that package will be installed by creating a hard linked copy in the virtual store (node_modules/.pnpm
).
如果将其设置为 false
或未设置,则将通过创建指向工作区中包的源目录的 node_modules
符号链接来安装依赖。这是默认设置,因为它更快并确保对依赖的任何修改都会立即对其消费者可见。
¥If this is set to false
or not set, then the dependency will instead be installed by creating a node_modules
symlink that points to the package's source directory in the workspace. This is the default, as it is faster and ensures that any modifications to the dependency will be immediately visible to its consumers.
例如,假设以下 package.json
是本地工作区包:
¥For example, suppose the following package.json
is a local workspace package:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0"
}
}
button
依赖通常会通过在 card
的 node_modules
目录中创建符号链接来安装,指向 button
的开发目录。
¥The button
dependency will normally be installed by creating a symlink in the node_modules
directory of card
, pointing to the development directory for button
.
但是,如果 button
在其 peerDependencies
中指定 react
,该怎么办?如果 monorepo 中的所有项目都使用相同版本的 react
,则没有问题。但是,如果使用 react@16
的 card
和使用 react@17
的 form
需要 button
,该怎么办?通常,你必须选择 react
的单个版本并使用 button
的 devDependencies
指定它。符号链接不提供让不同消费者(例如 card
和 form
)以不同方式满足 react
对等依赖的方法。
¥But what if button
specifies react
in its peerDependencies
? If all projects in the monorepo use the same version of react
, then there is no problem. But what if button
is required by card
that uses react@16
and form
that uses react@17
? Normally you'd have to choose a single version of react
and specify it using devDependencies
of button
. Symlinking does not provide a way for the react
peer dependency to be satisfied differently by different consumers such as card
and form
.
injected
字段通过在虚拟存储中安装 button
的硬链接副本来解决此问题。为了实现这一点,card
的 package.json
可以配置如下:
¥The injected
field solves this problem by installing a hard linked copies of button
in the virtual store. To accomplish this, the package.json
of card
could be configured as follows:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0",
"react": "16"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
而 form
的 package.json
可以配置如下:
¥Whereas the package.json
of form
could be configured as follows:
{
"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
。
¥With these changes, we say that button
is an "injected dependency" of card
and form
. When button
imports react
, it will resolve to react@16
in the context of card
, but resolve to react@17
in the context of form
.
由于注入的依赖会生成其工作区源目录的副本,因此每当修改代码时都必须以某种方式更新这些副本;否则,新状态将不会反映给消费者。当使用 pnpm --recursive run build
等命 令构建多个项目时,此更新必须在每个注入的包重建之后但在其使用者重建之前进行。对于简单的用例,可以通过再次调用 pnpm install
来实现,也许使用 package.json
生命周期脚本(例如 "prepare": "pnpm run build"
)来重建该项目。第三方工具(如 pnpm-sync 和 pnpm-sync-dependencies-meta-injected)为更新注入的依赖以及监视模式支持提供了更强大和高效的解决方案。
¥Because injected dependencies produce copies of their workspace source directory, these copies must be updated somehow whenever the code is modified; otherwise, the new state will not be reflected for consumers. When building multiple projects with a command such as pnpm --recursive run build
, this update must occur after each injected package is rebuilt but before its consumers are rebuilt. For simple use cases, it can be accomplished by invoking pnpm install
again, perhaps using a package.json
lifecycle script such as "prepare": "pnpm run build"
to rebuild that one project. Third party tools such as pnpm-sync and pnpm-sync-dependencies-meta-injected provide a more robust and efficient solution for updating injected dependencies, as well as watch mode support.
peerDependenciesMeta
此字段列出了与 peerDependencies
字段中列出的依赖相关的一些额外信息。
¥This field lists some extra information related to the dependencies listed in
the peerDependencies
field.
peerDependenciesMeta.*.optional
如果将其设置为 true,则包管理器将把所选的对等依赖标记为可选。因此,省略它的消费者将不再被报告为错误。
¥If this is set to true, the selected peer dependency will be marked as optional by the package manager. Therefore, the consumer omitting it will no longer be reported as an error.
例如:
¥For example:
{
"peerDependencies": {
"foo": "1"
},
"peerDependenciesMeta": {
"foo": {
"optional": true
},
"bar": {
"optional": true
}
}
}
请注意,即使 peerDependencies
中未指定 bar
,它也被标记为可选。因此,pnpm 将假定任何版本的 bar 都可以。但是,foo
是可选的,但仅限于所需的版本规范。
¥Note that even though bar
was not specified in peerDependencies
, it is
marked as optional. pnpm will therefore assume that any version of bar is fine.
However, foo
is optional, but only to the required version specification.
publishConfig
在打包包之前,可以覆盖清单中的某些字段。以下字段可以被覆盖:
¥It is possible to override some fields in the manifest before the package is packed. The following fields may be overridden:
-
cpu
-
os
要覆盖字段,请将字段的发布版本添加到 publishConfig
。
¥To override a field, add the publish version of the field to publishConfig
.
例如,以下 package.json
:
¥For instance, the following package.json
:
{
"name": "foo",
"version": "1.0.0",
"main": "src/index.ts",
"publishConfig": {
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
}
将发布为:
¥Will be published as:
{
"name": "foo",
"version": "1.0.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
publishConfig.executableFiles
默认情况下,出于可移植性原因,除了 bin 字段中列出的文件之外,生成的包存档中不会将任何文件标记为可执行文件。executableFiles
字段允许你声明必须设置可执行标志 (+x) 的其他文件,即使它们不能直接通过 bin 字段访问。
¥By default, for portability reasons, no files except those listed in the bin field will be marked as executable in the resulting package archive. The executableFiles
field lets you declare additional files that must have the executable flag (+x) set even if they aren't directly accessible through the bin field.
{
"publishConfig": {
"executableFiles": [
"./dist/shim.js"
]
}
}
publishConfig.directory
你还可以使用字段 publishConfig.directory
自定义相对于当前 package.json
的已发布子目录。
¥You also can use the field publishConfig.directory
to customize the published subdirectory relative to the current package.json
.
预计在指定目录中会有当前包的修改版本(通常使用第三方构建工具)。
¥It is expected to have a modified version of the current package in the specified directory (usually using third party build tools).
在此示例中,
"dist"
文件夹必须包含package.json
¥In this example the
"dist"
folder must contain apackage.json
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
}
}
publishConfig.linkDirectory
-
默认:true
¥Default: true
-
类型:布尔值
¥Type: Boolean
当设置为 true
时,项目将在本地开发期间从 publishConfig.directory
位置进行符号链接。
¥When set to true
, the project will be symlinked from the publishConfig.directory
location during local development.
例如:
¥For example:
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist",
"linkDirectory": true
}
}