In modern full-stack development, maintaining multiple interdependent projects can become complex. Developers often face challenges like inconsistent dependencies, duplicated configurations, and difficulties in coordinating releases. Monorepos provide a solution by housing multiple projects within a single repository, simplifying dependency management, and enabling cross-package collaboration. In this article, we will explore managing full-stack monorepos using Turborepo and pnpm Workspaces, covering setup, workflow optimization, and best practices.
1. What is a Monorepo?
A monorepo is a repository that contains multiple projects, often including frontend, backend, shared libraries, and utilities. Instead of splitting code into multiple repositories, a monorepo centralizes all codebases, which offers several advantages:
- Unified dependency management: Avoid version mismatches between related packages.
- Code sharing: Easily import shared utilities across projects.
- Streamlined CI/CD: Build and test multiple projects together.
2. Introducing Turborepo
Turborepo is a high-performance build system for JavaScript and TypeScript monorepos. It provides:
- Task pipelines with caching and concurrency
- Incremental builds and tests
- Seamless integration with npm, pnpm, and Yarn
Using Turborepo allows teams to run only the tasks affected by changes, dramatically reducing build times.
// Example: turborepo.json configuration
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"lint": {},
"test": {
"dependsOn": ["build"]
}
}
}
3. pnpm Workspaces
pnpm Workspaces is a monorepo feature that allows multiple packages to be managed within a single repository. Key benefits include:
- Efficient disk usage through symlinks
- Automatic dependency linking between local packages
- Consistent dependency versions across packages
Setting up pnpm Workspaces involves creating a root pnpm-workspace.yaml:
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
Here, apps/* might contain your frontend and backend projects, while packages/* contains shared libraries.
4. Project Structure Example
A typical full-stack monorepo structure using Turborepo and pnpm Workspaces:
my-monorepo/
├─ apps/
│ ├─ frontend/
│ └─ backend/
├─ packages/
│ ├─ ui-library/
│ └─ utils/
├─ package.json
├─ pnpm-workspace.yaml
└─ turbo.json
This structure allows easy sharing of code between frontend, backend, and utility packages.
5. Building and Testing
With Turborepo, you can define tasks in the turbo.json to build, test, and lint projects. Turborepo intelligently runs only tasks affected by code changes:
{
"pipeline": {
"build": { "outputs": ["dist/**"] },
"test": { "dependsOn": ["build"] }
}
}
Then, run tasks using the Turborepo CLI:
# Build all projects
npx turbo run build
# Run tests for affected projects
npx turbo run test
6. Sharing Dependencies and Code
Using pnpm Workspaces, you can share dependencies between projects without duplication:
// Example: frontend/package.json
{
"name": "frontend",
"dependencies": {
"react": "^18.2.0",
"ui-library": "workspace:*"
}
}
The workspace:* syntax ensures the local version of ui-library is used instead of fetching it from the npm registry.
“Monorepos simplify dependency management, but tooling like Turborepo and pnpm Workspaces makes it performant and scalable.”
7. Best Practices
- Keep shared code in
packages/to avoid duplication. - Use Turborepo caching to speed up CI/CD pipelines.
- Pin dependency versions to ensure reproducible builds.
- Run linting and formatting consistently across all packages.
- Use incremental builds to save developer time.
8. Conclusion
Managing full-stack monorepos can be challenging without the right tools. Turborepo and pnpm Workspaces provide an efficient and scalable approach, enabling teams to maintain consistency, share code, and optimize build performance. By following best practices, teams can achieve faster development cycles, improved collaboration, and reliable builds across multiple projects.
Monorepos are no longer limited to large enterprises. With Turborepo and pnpm Workspaces, small to medium-sized teams can leverage monorepo advantages without sacrificing performance or developer productivity.