Monorepos com Nx e Turborepo: A Revolução em Projetos JavaScript 2025
Olá HaWkers, monorepos se tornaram o padrão para projetos JavaScript em escala. Google, Facebook, Microsoft - gigantes da tech gerenciam milhões de linhas de código em repositórios únicos. E agora, com Nx e Turborepo, essa arquitetura está acessível para todos.
Você ainda gerencia múltiplos repos desconectados? Está perdendo velocidade e consistência.
O Que São Monorepos (E Por Que Importam)
Monorepo é estratégia arquitetural onde múltiplos projetos vivem em um único repositório, compartilhando código, ferramentas e configurações.
Vantagens Decisivas:
Compartilhamento de Código Trivial: Não precisa publicar pacotes NPM internos. Imports diretos entre projetos.
Refatoração Atômica: Mude interface? Atualize todos usos em um único commit. Impossível em polyrepos.
Tooling Unificado: ESLint, TypeScript, Prettier - uma configuração para tudo.
Builds Inteligentes: Ferramentas como Nx e Turborepo sabem exatamente o que mudou e compilam apenas o necessário.
Visibilidade Total: Veja impacto de mudanças em todo ecossistema imediatamente.
// Estrutura típica de monorepo
{
"apps": {
"web": "Next.js app principal",
"admin": "Dashboard administrativo",
"mobile": "React Native app"
},
"packages": {
"ui": "Biblioteca de componentes compartilhados",
"utils": "Utilidades comuns",
"api-client": "Cliente API tipado",
"config": "Configurações compartilhadas"
}
}// Nx - Monorepo poderoso e extensível
// nx.json - Configuração do Nx
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
// Caching distribuído - compartilhe entre time
"cacheableOperations": ["build", "test", "lint"],
"parallel": 3
}
}
},
"targetDefaults": {
"build": {
// Dependências automáticas
"dependsOn": ["^build"],
"inputs": [
"production",
"^production"
],
"outputs": ["{projectRoot}/dist"]
}
}
}
// apps/web/project.json
{
"name": "web",
"targets": {
"build": {
"executor": "@nx/next:build",
"options": {
"outputPath": "dist/apps/web"
}
},
"serve": {
"executor": "@nx/next:server",
"options": {
"port": 3000
}
}
},
// Nx detecta dependências automaticamente
"implicitDependencies": []
}
// Turborepo - Velocidade extrema
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
// Define quais outputs podem ser cacheados
"outputs": ["dist/**", ".next/**"],
// Depende de build dos pacotes usados
"dependsOn": ["^build"],
// Variáveis de ambiente afetam cache
"env": ["NODE_ENV"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
// Testes podem rodar em paralelo
"cache": true
},
"lint": {
// Não depende de nada, roda em paralelo
"cache": true
},
"dev": {
// Dev não faz cache (estado mutável)
"cache": false,
"persistent": true
}
}
}
// package.json na raiz
{
"name": "monorepo",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
],
"scripts": {
// Nx commands
"build": "nx run-many --target=build --all",
"test": "nx run-many --target=test --all",
"affected:build": "nx affected --target=build",
// Turborepo commands
"turbo:build": "turbo run build",
"turbo:test": "turbo run test --parallel"
},
"devDependencies": {
"nx": "^17.0.0",
"turbo": "^1.10.0"
}
}
// Exemplo prático: Biblioteca compartilhada
// packages/ui/src/Button.tsx
export interface ButtonProps {
variant: 'primary' | 'secondary';
children: React.ReactNode;
onClick?: () => void;
}
export function Button({ variant, children, onClick }: ButtonProps) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{children}
</button>
);
}
// packages/ui/package.json
{
"name": "@monorepo/ui",
"version": "1.0.0",
"main": "./src/index.ts",
"types": "./src/index.ts"
}
// apps/web usa a biblioteca
// apps/web/pages/index.tsx
// Import direto - não precisa npm install!
import { Button } from '@monorepo/ui';
export default function Home() {
return (
<div>
<h1>Welcome</h1>
{/* TypeScript funciona perfeitamente */}
<Button variant="primary" onClick={() => alert('Clicked!')}>
Get Started
</Button>
</div>
);
}
// Mudança na biblioteca reflete imediatamente
// Nx/Turborepo rebuildam apenas o necessário
// Exemplo de affected builds (Nx)
// Apenas projetos afetados por mudanças são recompilados
// Comando: nx affected:build --base=main
// Nx analisa git diff e compila apenas:
// - Projetos com arquivos modificados
// - Projetos que dependem dos modificados
// Caching inteligente
// Primeira build: 45 segundos
// Segunda build (sem mudanças): 0.1 segundos (cache)
// Build com mudança em 1 pacote: 5 segundos (apenas afetados)
Nx vs Turborepo: Qual Escolher?
Nx: Poder e Flexibilidade
Pontos Fortes:
- Ecosystem rico (plugins para React, Angular, Node, etc)
- Dependency graph visualization
- Code generators poderosos
- Distributed task execution
- Nx Cloud para cache remoto
Ideal Para:
- Projetos enterprise complexos
- Times que valorizam DX
- Necessidade de customização profunda
Turborepo: Simplicidade e Velocidade
Pontos Fortes:
- Configuração minimal
- Performance extrema
- Caching distribuído nativo
- Integração perfeita com Vercel
- Curva de aprendizado suave
Ideal Para:
- Startups que precisam mover rápido
- Projetos focados em web apps
- Times que querem simplicidade
Padrões de Organização
Estrutura por Tipo
monorepo/
├── apps/ # Aplicações deployáveis
│ ├── web/
│ ├── api/
│ └── admin/
├── packages/ # Bibliotecas compartilhadas
│ ├── ui/
│ ├── utils/
│ └── config/
└── tools/ # Ferramentas de buildEstrutura por Domínio
monorepo/
├── domains/
│ ├── auth/
│ │ ├── app/
│ │ ├── api/
│ │ └── ui/
│ └── billing/
│ ├── app/
│ ├── api/
│ └── ui/
└── shared/
├── ui/
└── utils/Desafios e Soluções
Tempo de CI Aumentado
Desafio: CI precisa testar tudo, leva tempo.
Solução: Use affected commands. Teste apenas o que mudou. Nx/Turborepo detectam automaticamente.
Merge Conflicts
Desafio: Mais código = mais conflitos.
Solução: Estrutura bem organizada minimiza conflitos. Lock files são o maior problema - use yarn ou pnpm que lidam melhor.
Codebase Grande
Desafio: IDEs lentas com muitos arquivos.
Solução: Use TypeScript project references. IDEs modernos (VS Code) lidam bem com workspaces.
Se você trabalha com TypeScript em monorepos, leia: TypeScript em 2025: Por Que 38% dos Desenvolvedores Usam Diariamente.

