pnpm 워크스페이스는 저장소 하나에 여러 패키지를 두고 한 번에 설치·연결·실행하는 기능이다. 루트의 pnpm-workspace.yaml에 패키지 위치를 적으면, 패키지끼리 npm 레지스트리에서 받는 대신 로컬 폴더 링크로 서로를 참조한다. 모노레포를 시작하는 가장 기본 단계다.
# pnpm-workspace.yaml
packages:
- apps/*
- packages/*workspace: 프로토콜
{
"dependencies": {
"@acme/ui": "workspace:*"
}
}workspace:로 적으면 pnpm은 반드시 워크스페이스 안의 패키지로만 해석한다. 없으면 레지스트리에서 받지 않고 설치가 실패하므로, 실수로 같은 이름의 외부 패키지를 받는 일이 없다- 의존 패키지가 로컬 폴더 링크이므로 공유 UI·설정 패키지를 고치면 레지스트리 배포 없이 앱에 반영된다(빌드 산출물을 내보내는 패키지라면 그 패키지 빌드는 필요하다)
pnpm publish·pnpm pack때는 실제 버전으로 바뀐다. 버전이1.5.0이면workspace:*→1.5.0,workspace:^→^1.5.0,workspace:~→~1.5.0
골라서 실행하기: --filter
pnpm --filter @acme/web dev # 한 패키지만
pnpm --filter "./apps/*" build # 경로 glob
pnpm --filter "@acme/ui..." test # ui와 ui가 의존하는 패키지들
pnpm --filter "...@acme/ui" test # ui와 ui에 의존하는 패키지들(영향 범위)
pnpm --filter "@acme/ui^..." test # ui가 의존하는 패키지들만(ui 제외)
pnpm --filter "...[origin/main]" test # origin/main 대비 바뀐 패키지와 그에 의존하는 것
pnpm -r build # 모든 패키지(의존 순서대로)...이 이름 뒤에 붙으면 의존 대상, 앞에 붙으면 의존하는 쪽까지 넓히고, ^를 함께 쓰면 자기 자신은 빠진다. pnpm -r의 run·exec·test는 기본으로 의존 대상을 먼저 실행하며, 워크스페이스 루트 패키지는 대상에서 빠진다. 공유 패키지를 고친 뒤 영향받는 앱만 테스트할 때는 ... 필터가 유용하다.
함께 알아 둘 것
- 잠금 파일(
pnpm-lock.yaml)은 기본 설정(sharedWorkspaceLockfile: true)에서 루트에 하나만 생긴다 - 루트
package.json에 공통 개발 도구를 추가할 때는pnpm add -D eslint -w처럼-w(--ignore-workspace-root-check)를 붙여야 한다. 없으면 실수 방지를 위해 실패한다 - 워크스페이스는 설치·연결과 의존 순서대로 실행하기까지 맡는다. 작업 결과 캐시와 바뀐 것만 다시 실행하는 최적화는 Turborepo나 Nx 같은 빌드 시스템이 맡는다
- pnpm의 저장 방식과 유령 의존성(Phantom Dependency) 차단은 npm과 pnpm을 본다
출처: pnpm — Workspace · pnpm — Workspace protocol · pnpm — Publishing workspace packages · pnpm — Filtering · pnpm — pnpm -r · pnpm — pnpm add: --ignore-workspace-root-check