乐闻世界logo
搜索文章和话题

How do npm workspaces enable monorepo management and what are the best practices?

2月17日 23:20

npm's monorepo support is implemented through the workspaces feature, allowing you to manage multiple related packages in a single repository. This is very useful for large projects and team collaboration.

Workspaces Basics

What Are Workspaces

Workspaces allow you to manage multiple packages in a single npm project. These packages can depend on each other and share dependencies.

Basic Configuration

Configure workspaces in the root package.json:

json
{ "name": "my-monorepo", "version": "1.0.0", "private": true, "workspaces": [ "packages/*" ], "scripts": { "install": "npm install -ws", "build": "npm run build -ws", "test": "npm test -ws", "clean": "npm run clean -ws" } }

Directory Structure

shell
my-monorepo/ ├── package.json ├── packages/ │ ├── shared/ │ │ ├── package.json │ │ └── index.js │ ├── app/ │ │ ├── package.json │ │ └── index.js │ └── utils/ │ ├── package.json │ └── index.js ├── node_modules/ │ ├── shared/ # Symbolic link to packages/shared │ ├── app/ # Symbolic link to packages/app │ └── utils/ # Symbolic link to packages/utils └── package-lock.json

Workspace Configuration Options

1. Array Format

json
{ "workspaces": [ "packages/*", "apps/*" ] }

2. Object Format

json
{ "workspaces": { "packages": [ "packages/*" ] } }

3. Mixed Format

json
{ "workspaces": { "packages": [ "packages/*", "apps/*" ], "nohoist": [ "**/lodash" ] } }

Workspace Commands

Install Dependencies

bash
# Install dependencies in all workspaces npm install -ws npm install --workspaces # Install dependencies in specific workspace npm install lodash --workspace=packages/app npm install lodash -w packages/app # Install workspace dependency npm install ../shared --workspace=packages/app

Run Scripts

bash
# Run scripts in all workspaces npm run build -ws npm run build --workspaces # Run scripts in specific workspace npm run build --workspace=packages/app npm run build -w packages/app # Run scripts in multiple workspaces npm run build -w packages/app -w packages/utils

Update Dependencies

bash
# Update dependencies in all workspaces npm update -ws # Update dependencies in specific workspace npm update --workspace=packages/app

Remove Dependencies

bash
# Remove dependencies from all workspaces npm uninstall lodash -ws # Remove dependencies from specific workspace npm uninstall lodash --workspace=packages/app

Inter-Workspace Dependencies

Add Workspace Dependency

bash
# Add dependency on packages/shared in packages/app cd packages/app npm install ../shared # Or use workspace name npm install shared --workspace=packages/app

package.json Example

packages/app/package.json:

json
{ "name": "app", "version": "1.0.0", "dependencies": { "shared": "*", "lodash": "^4.17.21" } }

packages/shared/package.json:

json
{ "name": "shared", "version": "1.0.0", "dependencies": { "lodash": "^4.17.21" } }

Advanced Configuration

1. nohoist Configuration

Prevent certain packages from being hoisted to the root:

json
{ "workspaces": { "packages": [ "packages/*" ], "nohoist": [ "**/lodash", "**/react", "**/webpack" ] } }

2. Private Packages

Ensure workspace packages are not published:

json
{ "name": "my-monorepo", "private": true, "workspaces": [ "packages/*" ] }

3. Shared Dependencies

Define shared dependencies in the root:

Root package.json:

json
{ "name": "my-monorepo", "version": "1.0.0", "private": true, "workspaces": [ "packages/*" ], "devDependencies": { "jest": "^29.0.0", "eslint": "^8.0.0", "typescript": "^5.0.0" } }

Practical Example

React + Express Monorepo

shell
my-monorepo/ ├── package.json ├── packages/ │ ├── web/ │ │ ├── package.json │ │ └── src/ │ ├── api/ │ │ ├── package.json │ │ └── src/ │ └── shared/ │ ├── package.json │ └── src/

Root package.json:

json
{ "name": "my-monorepo", "version": "1.0.0", "private": true, "workspaces": [ "packages/*" ], "scripts": { "install": "npm install -ws", "build": "npm run build -ws", "dev": "npm run dev -ws", "test": "npm test -ws", "lint": "npm run lint -ws" } }

packages/web/package.json:

json
{ "name": "web", "version": "1.0.0", "dependencies": { "react": "^18.0.0", "shared": "*" } }

packages/api/package.json:

json
{ "name": "api", "version": "1.0.0", "dependencies": { "express": "^4.18.0", "shared": "*" } }

packages/shared/package.json:

json
{ "name": "shared", "version": "1.0.0", "dependencies": { "lodash": "^4.17.21" } }

Best Practices

1. Unified Version Management

json
{ "scripts": { "version": "npm version --workspaces", "publish": "npm publish --workspaces" } }

2. Shared Configuration

json
{ "devDependencies": { "jest": "^29.0.0", "eslint": "^8.0.0", "prettier": "^3.0.0" } }

3. Unified Scripts

json
{ "scripts": { "build": "npm run build -ws", "test": "npm test -ws", "lint": "npm run lint -ws", "clean": "npm run clean -ws" } }

4. Use Lerna (Optional)

Lerna is a tool specifically designed for managing JavaScript monorepos:

bash
# Install Lerna npm install -g lerna # Initialize Lerna lerna init # Run commands lerna run build lerna publish

Common Issues

1. Dependency Conflicts

bash
# Check dependencies npm ls -ws # Use overrides to resolve conflicts npm config set overrides '{"package": "1.2.3"}'
bash
# Check symbolic links ls -la node_modules/ # Reinstall rm -rf node_modules package-lock.json npm install -ws

3. TypeScript Path Issues

tsconfig.json:

json
{ "compilerOptions": { "baseUrl": ".", "paths": { "shared": ["packages/shared/src"], "app": ["packages/app/src"] } } }

4. Build Order Issues

bash
# Build in order npm run build --workspace=packages/shared npm run build --workspace=packages/app npm run build --workspace=packages/api

Integration with Other Tools

1. TypeScript

json
{ "references": [ { "path": "./packages/shared" }, { "path": "./packages/app" } ] }

2. Jest

json
{ "projects": [ "<rootDir>/packages/*/jest.config.js" ] }

3. ESLint

json
{ "overrides": [ { "files": ["packages/*/src/**/*.ts"], "extends": ["@mycompany/eslint-config"] } ] }

4. Webpack

javascript
module.exports = { resolve: { alias: { shared: path.resolve(__dirname, 'packages/shared/src') } } };

Performance Optimization

1. Parallel Builds

bash
# Run scripts in parallel npm run build -ws --parallel

2. Incremental Builds

bash
# Only build changed packages npm run build -ws --if-present

3. Caching

bash
# Use cache npm install -ws --prefer-offline

Monitoring and Debugging

1. View Workspace Information

bash
# List all workspaces npm workspaces info # View specific workspace npm workspaces info --workspace=packages/app

2. Debug Dependencies

bash
# View dependency tree npm ls -ws # View dependencies of specific package npm ls shared -ws

3. View Installation Logs

bash
# Verbose logging npm install -ws --verbose # Debug logging npm install -ws --loglevel=verbose

npm workspaces is a powerful tool for managing monorepos, which can significantly improve development efficiency and maintainability of large projects.

标签:NPM