Files
pnpm/pnpm11/docs/settings/peer-dependencies.md
Zoltan KochanandClaude Opus 5.5 6f95957063 docs: lint prose with Vale (#17238)
* docs: lint prose with Vale

Add Vale with an in-repo style, .vale/styles/pnpm, that turns the
writing rules in AGENTS.md and the Google developer documentation style
guide into lint rules. The stock Vale packages (Google, Microsoft,
RedHat, write-good) were too noisy to block on, for example 1,300
passive-voice hits in the v12 docs alone, so the rules are written for
this repo, following the GitLab model. Each one links the guideline it
enforces.

Levels:
- error, fails CI: dashes, plain-word substitutions, condescending
  words, "please", "note that", hedges, puffery, optional plurals,
  exclamation marks, ellipses, curly quotes, generic link text, product
  spellings, sentence-case headings, repeated words, double spaces,
  implementation history in comments; in changesets, bold or italic
  emphasis, internal names and release-line names.
- warning: future tense, sentences over 30 words, "instead of" and
  "so that" tails in changesets.
- suggestion: passive voice.

.vale.ini scopes the rules. Docs get every rule. Contributor Markdown
and code comments keep dashes and headings as warnings until their
roughly 8,100 em dashes are rewritten. Released changesets stay in
.changeset/ and are not rewritten, so lint-prose.mjs lints only the
changesets added since PROSE_BASE (the PR base in CI).

The prose workflow installs a pinned, checksum-verified Vale release and
runs `pnpm lint:prose`. The rest of this change rewrites the existing
docs, READMEs, contributor Markdown, and code comments to pass the
error-level rules. Only prose and comment text changed. Renamed
headings keep their anchors.

Spelling stays with cspell, which checks identifiers that Vale does not
see.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: keep prose lint from flattening meaning

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:48:09 +02:00

7.4 KiB

id, title, sidebar_label
id title sidebar_label
peer-dependencies Peer Dependency Settings Peer dependencies

autoInstallPeers

  • Default: true
  • Type: Boolean

When true, any missing non-optional peer dependencies are automatically installed.

Optional peer dependencies

pnpm installs a missing optional peer dependency only if the workspace already has a version of it that satisfies the optional peer range. In that case, pnpm resolves the optional peer to that version. That version can come from any project in the workspace, including another project's devDependencies. For example, if one project depends on webpack and another has webpack-cli in its devDependencies, both projects get the webpack instance that has webpack-cli as its optional peer.

pnpm also resolves optional peers this way when dedupePeerDependents is true. To stop it, set both autoInstallPeers and dedupePeerDependents to false.

Version conflicts

If there are conflicting version requirements for a peer dependency from different packages, pnpm will not install any version of the conflicting peer dependency automatically. Instead, a warning is printed. For example, if one dependency requires react@^16.0.0 and another requires react@^17.0.0, these requirements conflict, and no automatic installation will occur.

Conflict resolution

In case of a version conflict, you'll need to evaluate which version of the peer dependency to install yourself, or update the dependencies to align their peer dependency requirements.

dedupePeerDependents

  • Default: true
  • Type: Boolean

When this setting is set to true, packages with peer dependencies will be deduplicated after peers resolution.

For instance, let's say we have a workspace with two projects and both of them have webpack in their dependencies. webpack has esbuild in its optional peer dependencies, and one of the projects has esbuild in its dependencies. In this case, pnpm will link two instances of webpack to the node_modules/.pnpm directory: one with esbuild and another one without it:

node_modules
  .pnpm
    webpack@1.0.0_esbuild@1.0.0
    webpack@1.0.0
project1
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0/node_modules/webpack
project2
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
    esbuild

This makes sense because webpack is used in two projects, and one of the projects doesn't have esbuild, so the two projects cannot share the same instance of webpack. However, this is not what most developers expect, especially since in a hoisted node_modules, there would only be one instance of webpack. Therefore, you may now use the dedupePeerDependents setting to deduplicate webpack when it has no conflicting peer dependencies (explanation at the end). In this case, if we set dedupePeerDependents to true, both projects will use the same webpack instance, which is the one that has esbuild resolved:

node_modules
  .pnpm
    webpack@1.0.0_esbuild@1.0.0
project1
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
project2
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack
    esbuild

What are conflicting peer dependencies? By conflicting peer dependencies we mean a scenario like the following one:

node_modules
  .pnpm
    webpack@1.0.0_react@16.0.0_esbuild@1.0.0
    webpack@1.0.0_react@17.0.0
project1
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0_react@17.0.0/node_modules/webpack
    react (v17)
project2
  node_modules
    webpack -> ../../node_modules/.pnpm/webpack@1.0.0_react@16.0.0_esbuild@1.0.0/node_modules/webpack
    esbuild
    react (v16)

In this case, we cannot dedupe webpack as webpack has react in its peer dependencies and react is resolved from two different versions in the context of the two projects.

dedupePeers

Added in: v10.33.0

  • Default: false
  • Type: Boolean

When enabled, peer dependency suffixes use version-only identifiers (name@version) instead of full dep paths, eliminating nested suffixes like (foo@1.0.0(bar@2.0.0)). This reduces the number of package instances in projects with many recursive peer dependencies.

This is different from dedupePeerDependents, which deduplicates packages that have the same peer dependencies across different workspace projects. dedupePeers simplifies the peer dependency suffix format itself.

strictPeerDependencies

  • Default: false
  • Type: Boolean

If this is enabled, commands will fail if there is a missing or invalid peer dependency in the tree.

resolvePeersFromWorkspaceRoot

  • Default: true
  • Type: Boolean

When enabled, dependencies of the root workspace project are used to resolve peer dependencies of any projects in the workspace. It is a useful feature as you can install your peer dependencies only in the root of the workspace, and you can be sure that all projects in the workspace use the same versions of the peer dependencies.

peerDependencyRules

peerDependencyRules.ignoreMissing

pnpm will not print warnings about missing peer dependencies from this list.

For instance, with the following configuration, pnpm will not print warnings if a dependency needs react but react is not installed:

peerDependencyRules:
  ignoreMissing:
  - react

Package name patterns may also be used:

peerDependencyRules:
  ignoreMissing:
  - "@babel/*"
  - "@eslint/*"

ignoreMissing matches the peer package name or a glob. It does not support the parent>peer or parent@range>peer selectors accepted by allowedVersions.

peerDependencyRules.allowedVersions

Unmet peer dependency warnings will not be printed for peer dependencies of the specified range.

For instance, if you have some dependencies that need react@16 but you know that they work fine with react@17, then you may use the following configuration:

peerDependencyRules:
  allowedVersions:
    react: "17"

This will tell pnpm that any dependency that has react in its peer dependencies should allow react v17 to be installed.

It is also possible to suppress the warnings only for peer dependencies of specific packages. For instance, with the following configuration react v17 will be only allowed when it is in the peer dependencies of the button v2 package or in the dependencies of any card package:

peerDependencyRules:
  allowedVersions:
    "button@2>react": "17"
    "card>react": "17"

peerDependencyRules.allowAny

allowAny is an array of package name patterns, any peer dependency matching the pattern will be resolved from any version, regardless of the range specified in peerDependencies. For instance:

peerDependencyRules:
  allowAny:
  - "@babel/*"
  - "eslint"

The above setting will mute any warnings about peer dependency version mismatches related to @babel/ packages or eslint.

allowAny matches the peer package name or a glob. It does not support the parent>peer or parent@range>peer selectors accepted by allowedVersions.