pnpm Workspaces: Quản lý packages trong monorepo frontend
Hướng dẫn toàn diện về pnpm workspaces — từ setup cơ bản, shared dependencies, đến các patterns nâng cao cho monorepo frontend.
pnpm đã trở thành package manager mặc định cho hầu hết monorepo frontend lớn. Lý do: nhanh hơn npm, tiết kiệm disk hơn yarn, và workspaces protocol mạnh mẽ. Bài này hướng dẫn setup pnpm workspaces từ đầu.
Tại sao pnpm cho monorepo?
- Content-addressable store: Mỗi package version chỉ lưu 1 lần trên disk, symlink vào node_modules
- Strict mode: Không cho access undeclared dependencies (phantom deps) — npm/yarn cho phép
- Workspace protocol:
workspace:*link internal packages tự động - Filtering:
pnpm --filterchạy commands cho specific packages
Setup cơ bản
# Install pnpm
corepack enable
corepack prepare pnpm@latest --activate
# Init monorepo
mkdir my-monorepo && cd my-monorepo
pnpm init
Tạo file pnpm-workspace.yaml:
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
Tạo cấu trúc thư mục:
mkdir -p apps/web apps/admin packages/ui packages/shared
Workspace protocol
Đây là killer feature của pnpm. Trong apps/web/package.json:
{
"name": "@myorg/web",
"dependencies": {
"@myorg/ui": "workspace:*",
"@myorg/shared": "workspace:*",
"react": "^19.0.0",
"next": "^15.0.0"
}
}
workspace:* nghĩa là: luôn dùng version hiện tại trong monorepo, không download từ registry. Khi publish, pnpm tự replace bằng actual version number.
Shared dependencies
Dependencies dùng chung nên hoist lên root để tránh duplicate:
# Install shared dev deps ở root
pnpm add -D -w typescript @types/node prettier
# Install cho specific package
pnpm --filter @myorg/web add next react react-dom
# Install cho tất cả packages matching pattern
pnpm --filter "@myorg/*" add -D vitest
Trong .npmrc:
# .npmrc
shamefully-hoist=false # Strict mode (recommended)
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=false giữ strict dependency resolution. Một số packages cũ có thể break — thêm chúng vào public-hoist-pattern nếu cần.
Filtering — chạy commands theo package
# Build chỉ web app và dependencies của nó
pnpm --filter @myorg/web... build
# Dấu ... = include dependencies
# Không có ... = chỉ package đó
# Lint tất cả packages đã thay đổi so với main
pnpm --filter "...[origin/main]" lint
# Dev mode cho web + ui (watch mode)
pnpm --filter @myorg/web --filter @myorg/ui dev
Scripts ở root package.json
{
"scripts": {
"dev": "pnpm --filter @myorg/web dev",
"dev:admin": "pnpm --filter @myorg/admin dev",
"dev:all": "pnpm -r --parallel dev",
"build": "pnpm -r build",
"lint": "pnpm -r lint",
"type-check": "pnpm -r type-check",
"clean": "pnpm -r exec rm -rf node_modules dist .next"
}
}
Overrides — fix dependency conflicts
Khi 2 packages depend on khác version cùng 1 library:
{
"pnpm": {
"overrides": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"typescript": "^5.5.0"
}
}
}
Điều này force tất cả packages dùng cùng version — tránh multiple React instances (bug phổ biến nhất trong monorepo React).
Checklist setup monorepo
- Tạo
pnpm-workspace.yamlvới đúng glob patterns - Set
shamefully-hoist=falsetrong.npmrc - Dùng
workspace:*cho internal dependencies - Shared devDependencies install ở root (
-wflag) - Dùng
overridesđể lock critical shared deps (React, TypeScript) - Setup
--filterscripts cho common tasks - Kết hợp với Turborepo để có caching và task pipeline
pnpm workspaces là foundation cho một monorepo tốt. Kết hợp với Turborepo (task runner) và Changesets (versioning), bạn có một setup production-ready cho team frontend.
Admin
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!