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.
engines
You can specify the version of Node and pnpm that your software works on:
{
"engines": {
"node": ">=10",
"pnpm": ">=3"
}
}
During local development, pnpm will always fail with an error message
if its version does not match the one specified in the
engines
field.
Unless the user has set the
engine-strict
config flag (see
.npmrc
), this
field is advisory only and will only produce warnings when your package is
installed as a dependency.
Additional meta information used for dependencies declared inside
dependencies
,
optionalDependencies
, and
devDependencies
.
If this is set to true for a local dependency, the package will be hard linked to the modules directory, not symlinked.
For instance, the following
package.json
in a workspace will create a symlink to
button
in the
node_modules
directory of
card
:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0"
}
}
But what if
button
has
react
in its peer dependencies? If all projects in the monorepo use the same version of
react
, then no problem. But what if
button
is required by
card
that uses
react@16
and
form
with
react@17
? Without using
inject
, you'd have to choose a single version of
react
and install it as dev dependency of
button
. But using the
injected
field you can inject
button
to a package, and
button
will be installed with the
react
version of that package.
So this will be the
package.json
of
card
:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0",
"react": "16"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
button
will be hard linked into the dependencies of
card
, and
react@16
will be symlinked to the dependencies of
card/node_modules/button
.
And this will be the
package.json
of
form
:
{
"name": "form",
"dependencies": {
"button": "workspace:1.0.0",
"react": "17"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
button
will be hard linked into the dependencies of
form
, and
react@17
will be symlinked to the dependencies of
form/node_modules/button
.
In contrast to normal dependencies, injected ones are not symlinked to the destination folder, so they are not updated automatically, e.g. after running the build script. To update the hard linked folder contents to the latest state of the dependency package folder, call
pnpm i
again.
Note that the
button
package must have any lifecycle script that runs on install in order for
pnpm
to detect the changes and update it. For example, the package can be rebuilt on install:
"prepare": "pnpm run build"
. Any script would work, even a simple unrelated command without side effects, like this:
"prepare": "pnpm root"
.
This field lists some extra information related to the dependencies listed in
the
peerDependencies
field.
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
}
}
}
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:
To override a field, add the publish version of the field to
publishConfig
.
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
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 fields 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
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).
In this example the
"dist"
folder must contain a
package.json
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
}
}
publishConfig.linkDirectory
-
Default:
true
-
Type:
Boolean
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
}
}
pnpm.overrides
This field allows you to instruct pnpm to override any dependency in the
dependency graph. This is useful to enforce all your packages to use a single
version of a dependency, backport a fix, or replace a dependency with a fork.
Note that the overrides field can only be set at the root of the project.
An example of the
"pnpm"."overrides"
field:
{
"pnpm": {
"overrides": {
"foo": "^1.0.0",
"quux": "npm:@myorg/quux@^1.0.0",
"bar@^2.1.0": "3.0.0",
"qar@1>zoo": "2"
}
}
}
You may specify the package the overriden dependency belongs to by
separating the package selector from the dependency selector with a ">", for
example
qar@1>zoo
will only override the
zoo
dependency of
qar@1
, not for
any other dependencies.
An override may be defined as a reference to a direct dependency's spec.
This is achieved by prefixing the name of the dependency with a
$
:
{
"dependencies": {
"foo": "^1.0.0"
},
"pnpm": {
"overrides": {
"foo": "$foo"
}
}
}
The referenced package does not need to match the overridden one:
{
"dependencies": {
"foo": "^1.0.0"
},
"pnpm": {
"overrides": {
"bar": "$foo"
}
}
}
pnpm.packageExtensions
The
packageExtensions
fields offer a way to extend the existing package definitions with additional information. For example, if
react-redux
should have
react-dom
in its
peerDependencies
but it has not, it is possible to patch
react-redux
using
packageExtensions
:
{
"pnpm": {
"packageExtensions": {
"react-redux": {
"peerDependencies": {
"react-dom": "*"
}
}
}
}
}
The keys in
packageExtensions
are package names or package names and semver ranges, so it is possible to patch only some versions of a package:
{
"pnpm": {
"packageExtensions": {
"react-redux@1": {
"peerDependencies": {
"react-dom": "*"
}
}
}
}
}
The following fields may be extended using
packageExtensions
:
dependencies
,
optionalDependencies
,
peerDependencies
, and
peerDependenciesMeta
.
A bigger example:
{
"pnpm": {
"packageExtensions": {
"express@1": {
"optionalDependencies": {
"typescript": "2"
}
},
"fork-ts-checker-webpack-plugin": {
"dependencies": {
"@babel/core": "1"
},
"peerDependencies": {
"eslint": ">= 6"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
}
}
}
}
}
}
Together with Yarn, we maintain a database of
packageExtensions
to patch broken packages in the ecosystem.