Node-Modules & Hoisting Settings
node_modules settings#
modulesDir#
- Default: node_modules
- Type: path
The directory in which dependencies will be installed (instead of
node_modules).
nodeLinker#
- Default: isolated
- Type: isolated, hoisted, pnp
Node.js のパッケージをインストールするのに使用するリンカーを指定します。
- isolated - dependencies are symlinked from a virtual store at
node_modules/.pnpm. - hoisted - a flat
node_moduleswithout symlinks is created. Same as thenode_modulescreated by npm or Yarn Classic. この設定を使用すると、Yarnのライブラリーの 1 つが巻き上げに使用されます。この設定を使用する合理的な理由は以下のとおりです:- 使っているツールはシンボリックリンクではうまく機能しない。
- プロジェクトがサーバーレスホスティングにデプロイされる。一部のサーバーレスサービスの提供者 (AWS Lambdaなど) はシンボリックリンクをサポートしていません。この問題を解決する代替策は、デプロイ前にアプリケーションをバンドルすることです。
- If you want to publish your package with
"bundledDependencies". - If you are running Node.js with the --preserve-symlinks flag.
- pnp - no
node_modules. Plug'n'Play is an innovative strategy for Node that is used by Yarn Berry. It is recommended to also setsymlinksetting tofalsewhen usingpnpas your linker.
nodeExperimentalPackageMap#
Added in: v11.8.0
- Default: false
- Type: Boolean
When true, pnpm writes node_modules/.package-map.json during isolated and hoisted installs and injects it into pnpm-managed Node.js script environments by adding Node's --experimental-package-map option to NODE_OPTIONS.
Nothing reads the map without this setting, so pnpm does not write one. An install that stops writing the map also removes one an earlier install left.
CLI and environment configuration use the kebab-case name node-experimental-package-map.
nodeExperimentalPackageMap: true
nodePackageMapType#
Added in: v11.8.0
- Default: standard
- Type: standard, loose
Controls how node_modules/.package-map.json is generated.
- standard - only declared dependencies are available through the package map.
- loose - also maps packages that are reachable through the installed
node_moduleslayout, which can allow undeclared hoisted dependencies to resolve.
CLI and environment configuration use the kebab-case name node-package-map-type.
nodePackageMapType: loose
symlink#
- Default: true
- Type: Boolean
When symlink is set to false, pnpm creates a virtual store directory without
any symlinks. It is a useful setting together with nodeLinker=pnp.
enableModulesDir#
- Default: true
- Type: Boolean
When false, pnpm will not write any files to the modules directory
(node_modules). この設定はユーザスペース上のファイルシステム (FUSE) にモジュールディレクトリがマウントされている場合に有用です。 There is an experimental CLI that allows you to
mount a modules directory with FUSE: @pnpm/mount-modules.
confirmModulesPurge#
- Default: true
- Type: Boolean
Controls whether pnpm asks for confirmation before removing the contents of an
incompatible modules directory and reinstalling it from scratch. When false,
pnpm recreates the modules directory without prompting. In CI, confirmation is
disabled automatically. If confirmation is enabled without a TTY and CI is not
detected, pnpm aborts with ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY.
virtualStoreDir#
- Default: node_modules/.pnpm
- Types: path
ストアにリンクするディレクトリを指定する。すべてのプロジェクトの直接および間接的な依存はこのディレクトリへリンクされる。
Dependencies installed from a URL or local path get a hash suffix on their directory name when the part after the scheme contains +, #, :, ?, or another character that is not allowed in file names. This keeps distinct URLs in separate directories.
Windows 上でのパスの長さ上限に関する問題を解決するのに役立ちます。 If
you have some dependencies with very long paths, you can select a virtual store
in the root of your drive (for instance C:\my-project-store).
Or you can set the virtual store to .pnpm and add it to .gitignore. 依存のディレクトリをひとつ上にすることで、スタックトレース上での表示がすっきりします。
NOTE: the virtual store cannot be shared between several projects. すべてのプロジェクトはそれぞれ固有の仮想ストアを持つ必要があります。 (ルートが共通のワークスペース内のプロジェクトは除く)
virtualStoreDirMaxLength#
- デフォルト:
- On Linux/macOS: 120
- On Windows: 60
- Types: number
Sets the maximum allowed length of directory names inside the virtual store directory (node_modules/.pnpm). You may set this to a lower number if you encounter long path issues on Windows.
virtualStoreOnly#
Added in: v11.0.0
- Default: false
- Type: Boolean
When set to true, pnpm populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts. pnpm fetch uses this mode internally.
packageImportMethod#
- Default: auto
- Type: auto, hardlink, copy, clone, clone-or-copy
Controls the way packages are imported from the store (if you want to disable symlinks inside node_modules, then you need to change the nodeLinker setting, not this one).
- auto - try to clone packages from the store. クローンがサポートされていない場合、ストアからパッケージをハードリンクします。クローンもリンクもできない場合は、コピーします。
- hardlink - hard link packages from the store
- clone-or-copy - try to clone packages from the store. クローンがサポートされていない場合、コピーにフォールバックします。
- copy - copy packages from the store
- clone - clone (AKA copy-on-write or reference link) packages from the store
クローンはパッケージを node_modules に書き込む最良の方法です。最速かつ最も安全です。クローンを使用している場合、node_modules 内のファイルを編集可能です(編集しても中央ストア側のファイルは変更されません)。
残念ながら、すべてのファイル システムがクローン作成をサポートしているわけではありません。 pnpmで最高の経験をするためには、コピーオンライト (CoW) ファイルシステム (例えばLinuxでは Ext4 の代わりに Btrfs) を使用することをお勧めします。
modulesCacheMaxAge#
- Default: 10080 (7 days in minutes)
- Type: number
孤立したパッケージを node_module ディレクトリから削除するまでの時間を分単位で指定します。
pnpm はパッケージのキャッシュを node_module ディレクトリに保持します。これにより、ブランチを切り替えたり、依存のダウングレードを行う際のインストールのスピードを速くします。
dlxCacheMaxAge#
- Default: 1440 (1 day in minutes)
- Type: number
The time in minutes after which dlx cache expires. After executing a dlx command, pnpm keeps a cache that omits the installation step for subsequent calls to the same dlx command.
virtualStoreType#
Added in: v11.23.0
- Default: project
- Type: project, global
Names where the virtual store lives: one store per project, or one store per machine.
virtualStoreType: global
project is the default layout: every project gets its own virtual store inside node_modules/.pnpm. global is the global virtual store: a single store shared by every project on the machine, with each project's node_modules holding only symlinks into it.
This is the canonical spelling of enableGlobalVirtualStore, which keeps working; when a project sets both, virtualStoreType wins. It can also be set through the PNPM_CONFIG_VIRTUAL_STORE_TYPE env variable and read back with pnpm config get virtualStoreType.
The setting is independent of nodeLinker: isolated and pnp both work with either store type, and hoisted writes no virtual store at all, so it is unaffected.
enableGlobalVirtualStore#
Added in: v10.12.1
- Default: false
- Type: Boolean
メモ
Since v11.23.0, virtualStoreType is the canonical spelling of this setting: enableGlobalVirtualStore: true is virtualStoreType: global. Both work, and virtualStoreType wins when a project sets both.
メモ
In pnpm v11, global installs (pnpm add -g) and pnpm dlx use the global virtual store by default.
When enabled, node_modules contains only symlinks to a central virtual store, rather than to node_modules/.pnpm. By default, this central store is located at <store-path>/links (use pnpm store path to find <store-path>).
In the central virtual store, each package is hard linked into a directory whose name is the hash of its dependency graph. As a result, all projects on the system can symlink their dependencies from this shared location on disk. This approach is conceptually similar to how NixOS manages packages, using dependency graph hashes to create isolated and shareable package directories in the Nix store.
This should not be confused with the global content-addressable store. The actual package files are still hard linked from the content-addressable store, but instead of being linked directly into
node_modules/.pnpm, they are linked into the global virtual store.
Using a global virtual store can speed up installations when a warm cache is available. However, in CI environments (where caches are typically absent), it may slow down installation. If pnpm detects that it is running in CI and this setting is not set, the global virtual store is off.
important
To support hoisted dependencies when using a global virtual store, pnpm relies on the NODE_PATH environment variable. This allows Node.js to resolve packages from the hoisted node_modules directory. Node.js does not respect NODE_PATH for ESM imports, though, so before v11.23.0 a dependency that imports a package not declared in its own package.json (which is considered bad practice) failed to resolve under ESM.
Since v11.23.0, every process pnpm spawns for the project (pnpm run, pnpm exec, lifecycle scripts, and the tools pnpm dlx runs) receives both NODE_PATH and a NODE_OPTIONS --import flag that registers a resolve hook restoring NODE_PATH lookups for ESM. Such imports now resolve for CommonJS and ESM alike, without the @pnpm/plugin-esm-node-path config dependency that used to be needed (#9618).
Two things fall outside that: a node process you start yourself rather than through pnpm, and a project that sets extendNodePath to false, which turns the whole NODE_PATH mechanism off and takes the resolve hook with it. Use packageExtensions to declare the missing dependencies if you need them to resolve in either case.
Dependency hoisting settings#
hoist#
- Default: true
- Type: boolean
When true, all dependencies are hoisted to node_modules/.pnpm/node_modules. This makes
unlisted dependencies accessible to all packages inside node_modules.
hoistPattern#
- Default: ['*']
- Type: string[]
Tells pnpm which packages should be hoisted to node_modules/.pnpm/node_modules. デフォルトでは、全てのパッケージが巻き上げられます。しかし、phantom dependency を持つ、扱いに困るパッケージの存在が分かっている場合には、このオプションにより、それらを除外して巻き上げることができます (推奨)。
例:
hoistPattern:
- "*eslint*"
- "*babel*"
You may also exclude patterns from hoisting using !.
例:
hoistPattern:
- "*types*"
- "!@types/react"
In a workspace, the pattern is matched against the names of the workspace projects too, unless hoistWorkspacePackages is turned off.
publicHoistPattern#
- Default: []
- Type: string[]
Unlike hoistPattern, which hoists dependencies to a hidden modules directory
inside the virtual store, publicHoistPattern hoists dependencies matching
the pattern to the root modules directory. ルートのモジュールディレクトリへの巻き上げによって、アプリケーションのコードは phantom dependencies へアクセスできるようになります。たとえ依存関係の解決方法が不適切に変更されたとしてもアクセス可能です。
この設定は、依存関係を適切に解決していなくて扱いに困る、プラグイン可能なツールを利用する場合に便利です。
例:
publicHoistPattern:
- "*plugin*"
Note: Setting shamefullyHoist to true is the same as setting
publicHoistPattern to *.
You may also exclude patterns from hoisting using !.
例:
publicHoistPattern:
- "*types*"
- "!@types/react"
In a workspace, the pattern is matched against the names of the workspace projects too, unless hoistWorkspacePackages is turned off.
hoistWorkspacePackages#
- Default: true
- Type: boolean
When true, the projects of the workspace are hoisting candidates too, not only the packages that come from a registry.
hoistPattern and publicHoistPattern then decide where each project lands, exactly as they do for a registry dependency. publicHoistPattern is checked first, so a project matching both patterns goes to the root only:
- A project whose name matches
publicHoistPatternis symlinked into<workspace_root>/node_modules. - A project whose name matches only
hoistPatternis symlinked into<workspace_root>/node_modules/.pnpm/node_modules. - A project whose name matches neither is not hoisted.
Because hoistPattern defaults to ['*'] and publicHoistPattern to [], the default is that every workspace project is symlinked into <workspace_root>/node_modules/.pnpm/node_modules.
This is how a tool that resolves packages by name from the workspace root finds a project of the workspace. The usual case is ESLint loading a plugin that is developed in the same monorepo:
publicHoistPattern:
- "*eslint*"
With that setting, a workspace project named eslint-plugin-acme appears at <workspace_root>/node_modules/eslint-plugin-acme, even if no package.json lists it as a dependency.
Details worth knowing:
- A project is matched by the
namein itspackage.json, not by its directory name. - Every project of the workspace is a candidate, including a project that nothing else depends on. The workspace root project is never hoisted.
- The symlink points at the project's own directory in the workspace, so there is nothing to keep in sync.
- A direct dependency wins a name conflict. If a package with the same name is a direct dependency of any workspace project, that package is hoisted and the workspace project is not. Frozen installs preserve this choice even when the dependency is unchanged.
- The setting only adds candidates. When
hoistPatternandpublicHoistPatternare both empty, nothing is hoisted at all, workspace projects included. SettinghoisttofalseemptieshoistPattern.
shamefullyHoist#
- Default: false
- Type: Boolean
By default, pnpm creates a semistrict node_modules, meaning dependencies have
access to undeclared dependencies but modules outside of node_modules do not.
エコシステム内のほとんどのパッケージは、この方法で問題なく動作します。
However, if some tooling only works when the hoisted dependencies are in the
root of node_modules, you can set this to true to hoist them for you.
hoistingLimits#
Added in: v11.5.0
- Default: none
- Type: none, workspaces, dependencies
Controls how far dependencies are hoisted when using nodeLinker: hoisted. This setting mirrors Yarn's nmHoistingLimits.
- none - hoist as far as possible (the default).
- workspaces - hoist only as far as each workspace package, preventing dependencies from being hoisted above the workspace package that depends on them.
- dependencies - hoist only up to each workspace package's direct dependencies, preventing transitive dependencies from being hoisted into the workspace package's
node_modules.