I’m working on a monorepo setup using pnpm
workspaces to manage multiple related projects. My goal is to efficiently manage and share dependencies across these projects without duplicating them in each project’s package.json
. However, I’m facing challenges with resolving shared dependencies and ensuring that binaries are correctly executed.
Context:
- Shared Dependencies: I want to maintain a set of common dependencies that can be used across different projects without listing them in every single
package.json
. This helps avoid redundancy and ensures consistency. - Binary Resolution: Some dependencies provide binaries (e.g.,
rimraf
) that need to be available when running scripts in individual projects. These binaries need to be correctly resolved, even if they are defined in a shared or root configuration. - Avoiding Dependency Bloat: Not all projects in the monorepo require all shared dependencies, so I want to avoid bloating each project’s
package.json
or the rootpackage.json
with unnecessary dependencies. - Modular Configurations: I prefer a modular approach where shared configurations and dependencies can be managed centrally but linked or used as needed in individual projects.
Current Setup:
-
pnpm-workspaces.yaml
packages: - "packages/*" - "packages-foo/*" - "packages-bar/*"
-
Root
package.json
(workspace root):{ "name": "monorepo-root", "devDependencies": { "eslint": "^7.32.0", "prettier": "^2.3.2", "rimraf": "^3.0.2" } }
-
Shared Configurations
package.json
(packages/shared/package.json):{ "name": "shared-config", "devDependencies": { "@faker-js/faker": "^7.4.0", "typescript": "^5.5.3" } }
-
API Package
package.json
(packages/api/package.json):{ "name": "api-package", "scripts": { "build": "pnpm exec rimraf dist && pnpm exec tsc", "lint": "pnpm exec eslint src --fix" }, "devDependencies": { "typescript": "workspace:*" } }
-
Web Package
package.json
(packages/web/package.json):{ "name": "web-package", "version": "1.0.0", "private": true, "scripts": { "build": "pnpm exec rimraf dist && pnpm exec tsc", "lint": "pnpm exec eslint src --fix" }, "devDependencies": { "typescript": "workspace:*" } }
Issues:
- Binaries Not Found: When running scripts in individual packages, binaries like
rimraf
are not found unless they are explicitly listed in each package’sdevDependencies
. - Shared Libraries: Dependencies like
@faker-js/faker
in theshared
package are not being resolved by other packages, such asapi-package
, even though they are intended to be shared.
Questions:
- How can I ensure that binaries from shared dependencies are correctly resolved and executed in individual package scripts?
- What is the best way to manage shared dependencies to avoid duplication and bloat, but still ensure they are available where needed?
- Are there any best practices or configurations for
pnpm
workspaces to handle this efficiently?
Is this even possible with pnpm
workspaces, or am I trying to achieve something that isn’t feasible?
Any guidance or examples of how to set this up effectively would be greatly appreciated!