Node-Modules & 호이스팅 설정
node_modules settings#
modulesDir#
- 기본값: node_modules
- 유형: path
종속성을 설치할 디렉터리입니다(node_modules 대신).
nodeLinker#
- 기본값: isolated
- 유형: isolated, hoisted, pnp
노드 패키지 설치에 사용해야 하는 링커를 정의합니다.
- isolated - 종속성이
node_modules/.pnpm에 있는 가상 스토어에서 심볼릭 링크됩니다. - hoisted - 심볼릭 링크가 없는 평탄한
node_modules가 생성됩니다. Yarn Classic 또는 npm이 생성하는node_modules와 동일합니다. 이 설정을 사용하면 Yarn의 라이브러리 중 하나가 호이스팅에 사용됩니다. 이 설정을 사용해야 하는 정당한 이유:- 여러분의 도구가 심볼릭 링크와 잘 작동하지 않습니다.
- 여러분의 프로젝트가 서버리스 호스팅 제공업체에 배포됩니다. 일부 서버리스 공급자 (예: AWS Lambda)는 심볼릭 링크를 지원하지 않습니다. 이 문제에 대한 대안 솔루션은 배포 전에 애플리케이션을 번들로 묶는 것입니다.
- 패키지를
"bundledDependencies"와 함께 게시하려는 경우. - --preserve-symlinks 플래그를 사용하여 Node.js를 실행하는 경우.
- pnp -
node_modules가 없습니다. Plug'n'Play는 Yarn Berry에서 사용하는 Node용 혁신적인 전략입니다.symlink설정을false로 함께 지정하는 것을 권장하며, 이는pnp를 링커로 사용할 때 적용됩니다.
nodeExperimentalPackageMap#
추가된 버전: v11.8.0
- 기본값: false
- 타입: 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 및 환경 구성에서는 케밥 케이스 이름 node-experimental-package-map을 사용합니다.
nodeExperimentalPackageMap: true
nodePackageMapType#
추가된 버전: v11.8.0
- 기본값: standard
- 유형: standard, loose
node_modules/.package-map.json이 생성되는 방식을 제어합니다.
- standard - 선언된 종속성만 패키지 맵을 통해 사용할 수 있습니다.
- loose - 설치된
node_modules레이아웃을 통해 도달할 수 있는 패키지도 매핑하므로, 선언되지 않은 호이스팅된 종속성이 해석될 수 있습니다.
CLI 및 환경 구성에서는 케밥 케이스 이름 node-package-map-type을 사용합니다.
nodePackageMapType: loose
symlink#
- 기본값: true
- 타입: Boolean
symlink가 false로 설정되면 pnpm은 심볼릭 링크 없이 가상 스토어 디렉터리를 생성합니다. nodeLinker=pnp와 함께 사용하면 유용한 설정입니다.
enableModulesDir#
- 기본값: true
- 타입: Boolean
false이면 pnpm은 모듈 디렉터리(node_modules)에 어떤 파일도 쓰지 않습니다. 이것은 모듈 디렉토리가 사용자 공간 (FUSE) 의 파일 시스템으로 마운트될 때 유용합니다. FUSE로 모듈 디렉터리를 마운트할 수 있는 실험적 CLI가 있습니다: @pnpm/mount-modules.
confirmModulesPurge#
- 기본값: true
- 타입: 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#
- 기본값: node_modules/.pnpm
- 유형: 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에서 긴 경로 문제를 해결할 수 있는 유용한 설정입니다. 매우 긴 경로를 가진 종속성이 있는 경우, 드라이브 루트에 있는 가상 스토어를 선택할 수 있습니다(예를 들어 C:\my-project-store).
또는 가상 스토어를 .pnpm으로 설정하고 .gitignore에 추가할 수 있습니다. 이렇게 하면 의존성 경로가 한 디렉토리 더 높기 때문에 스택 트레이스를 더 깔끔하게 만들 수 있습니다.
참고: 가상 스토어는 여러 프로젝트 간에 공유할 수 없습니다. 모든 프로젝트에는 자체 가상 저장소가 있어야 합니다(루트가 공유되는 워크스페이스 제외).
virtualStoreDirMaxLength#
- 기본값:
- Linux/macOS 환경: 120
- Windows 환경: 60
- 유형: number
가상 스토어 디렉터리(node_modules/.pnpm) 내부 디렉터리 이름의 최대 허용 길이를 설정합니다. Windows에서 긴 경로 문제가 발생하면 이 값을 더 낮게 설정할 수 있습니다.
virtualStoreOnly#
추가된 버전: v11.0.0
- 기본값: false
- 타입: Boolean
true로 설정하면 pnpm은 임포터 심볼릭 링크 생성, 호이스팅, bin 링크 생성 또는 라이프사이클 스크립트 실행 없이 가상 스토어를 채웁니다. 이는 불필요한 프로젝트 수준 아티팩트를 만들지 않고 스토어를 미리 채울 때(예를 들어, Nix 빌드에서) 유용합니다. pnpm fetch는 내부적으로 이 모드를 사용합니다.
packageImportMethod#
- 기본값: auto
- 유형: auto, hardlink, copy, clone, clone-or-copy
스토어에서 패키지를 가져오는 방식을 제어합니다(node_modules 내부의 심볼릭 링크를 비활성화하려면 이 설정이 아니라 nodeLinker 설정을 변경해야 합니다).
- auto - 스토어에서 패키지 복제를 시도합니다. 복제가 지원되지 않으면 저장소에서 패키지를 하드링크합니다. 복제도, 연결도 불가능하면 복사로 대체합니다.
- hardlink - 스토어에서 패키지를 하드 링크합니다
- clone-or-copy - 스토어에서 패키지 복제를 시도합니다. 복제가 지원되지 않으면 복사로 대체합니다.
- copy - 스토어에서 패키지를 복사합니다
- clone - 스토어에서 패키지를 복제(copy-on-write 또는 reference link라고도 함)합니다
node_modules에 패키지를 작성할 때 복제가 가장 좋은 방법입니다. 가장 빠르고 안전한 방법입니다. 복제를 사용하면 node_modules에서 파일을 편집할 수 있으며, 이는 중앙 content-addressable 저장소에서 수정되지 않습니다.
불행히도 모든 파일 시스템이 복제를 지원하는 것은 아닙니다. 최고의 pnpm 경험을 위해 CoW(Copy-On-Write) 파일 시스템(예: Linux에서 Ext4 대신 Btrfs)을 사용하는 것이 좋습니다.
modulesCacheMaxAge#
- 기본값: 10080 (분 단위로 7일)
- 유형: number
모듈 디렉토리에서 고아 패키지를 제거해야 하는 시간(분)입니다. pnpm은 모듈 디렉토리에 패키지 캐시를 유지합니다. 이렇게 하면 브랜치를 전환하거나 의존성을 다운그레이드할 때 설치 속도가 향상됩니다.
dlxCacheMaxAge#
- 기본값: 1440 (분 단위로 1일)
- 유형: number
분 단위로 지정하는 dlx 캐시 만료 시간입니다. 어떤 dlx 명령을 실행한 후, pnpm은 동일한 dlx 명령의 후속 호출에서 설치 단계를 생략하는 캐시를 유지합니다.
virtualStoreType#
추가된 버전: 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#
버전 10.12.1에서 추가됨
- 기본값: false
- 타입: 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.
참고
버전 v11에서는 전역 설치(pnpm add -g)와 pnpm dlx가 기본적으로 글로벌 가상 스토어를 사용합니다.
활성화하면 node_modules에는 node_modules/.pnpm이 아닌 중앙 가상 스토어에 대한 심볼릭 링크만 포함됩니다. 기본적으로 이 중앙 스토어는 <store-path>/links에 있습니다(pnpm store path로 <store-path>의 위치를 확인하세요).
중앙 가상 스토어에서 각 패키지는 종속성 그래프의 해시를 이름으로 하는 디렉터리에 하드 링크됩니다. 그 결과 시스템의 모든 프로젝트가 디스크의 이 공유 위치에서 종속성을 심볼릭 링크할 수 있습니다. 이 접근 방식은 NixOS가 패키지를 관리하는 방식과 개념적으로 유사하며, 종속성 그래프 해시를 사용하여 Nix 스토어에 격리되고 공유 가능한 패키지 디렉터리를 생성합니다.
이를 전역 콘텐츠 주소 지정 방식 스토어와 혼동해서는 안 됩니다. 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. 그러나 CI 환경(일반적으로 캐시가 없는 환경)에서는 설치 속도가 느려질 수 있습니다. If pnpm detects that it is running in CI and this setting is not set, the global virtual store is off.
important
전역 가상 스토어를 사용할 때 호이스팅된 종속성을 지원하기 위해 pnpm은 NODE_PATH 환경 변수에 의존합니다. 이를 통해 Node.js가 호이스팅된 node_modules 디렉터리에서 패키지를 해석할 수 있습니다. 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#
- 기본값: true
- 유형: boolean
true이면 모든 종속성이 node_modules/.pnpm/node_modules로 호이스팅됩니다. 이렇게 하면 목록에 없는 종속성을 node_modules 내부의 모든 패키지에서 접근할 수 있습니다.
hoistPattern#
- 기본값: ['*']
- 유형: string[]
어떤 패키지를 node_modules/.pnpm/node_modules로 호이스팅할지 pnpm에 알려줍니다. 기본적으로 모든 패키지는 호이스팅됩니다, 하지만 유령 의존성을 갖는 잘못된 패키지를 알고 있다면 이 옵션을 이용해 유령 의존성을 호이스팅할 수 있습니다. (권장)
예를 들어:
hoistPattern:
- "*eslint*"
- "*babel*"
!를 사용하여 패턴을 호이스팅에서 제외할 수도 있습니다.
예를 들어:
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#
- 기본값: []
- 유형: string[]
가상 스토어 내부의 숨겨진 모듈 디렉터리로 종속성을 호이스팅하는 hoistPattern과 달리, publicHoistPattern은 패턴과 일치하는 종속성을 루트 모듈 디렉터리로 호이스팅합니다. 루트 모듈 디렉토리에 대한 호이스팅은 애플리케이션 코드가 해결 전략을 부적절하게 수정하더라도 유령 의존성에 액세스할 수 있음을 의미합니다.
이 설정은 의존성을 제대로 해결하지 못하는 일부 결함이 있는 플러그형 도구를 처리할 때 유용합니다.
예를 들어:
publicHoistPattern:
- "*plugin*"
참고: shamefullyHoist를 true로 설정하는 것은 publicHoistPattern을 *로 설정하는 것과 같습니다.
!를 사용하여 패턴을 호이스팅에서 제외할 수도 있습니다.
예를 들어:
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#
- 기본값: true
- 유형: 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#
- 기본값: false
- 유형: Boolean
기본적으로 pnpm은 반엄격 node_modules를 생성하는데, 이는 종속성은 선언되지 않은 종속성에 접근할 수 있지만 node_modules 외부의 모듈은 접근할 수 없음을 의미합니다.
이 레이아웃을 사용하면 생태계의 대부분의 패키지가 문제 없이 작동합니다.
그러나 일부 도구가 호이스팅된 종속성이 node_modules의 루트에 있을 때만 동작한다면, 이 값을 true로 설정하여 종속성을 호이스팅할 수 있습니다.
hoistingLimits#
추가된 버전: v11.5.0
- 기본값: none
- 유형: none, workspaces, dependencies
nodeLinker: hoisted를 사용할 때 종속성을 얼마나 멀리 호이스팅할지 제어합니다. 이 설정은 Yarn의 nmHoistingLimits와 동일합니다.
- none - 가능한 한 멀리 호이스팅합니다(기본값).
- workspaces - 각 워크스페이스 패키지까지만 호이스팅하여, 종속성이 해당 종속성을 사용하는 워크스페이스 패키지보다 위로 호이스팅되지 않도록 합니다.
- dependencies - 각 워크스페이스 패키지의 직접 종속성까지만 호이스팅하여, 전이 종속성이 워크스페이스 패키지의
node_modules로 호이스팅되지 않도록 합니다.