5 apps num único repositório - o monorepo Turborepo de um dev solo
Como montar um monorepo Turborepo para gerenciar vários apps e sites num único repositório. Compartilhamento de configurações, economia de build com cache e deploy por app, tudo do ponto de vista prático.
Resumo
Quando você cria vários apps sozinho, as configurações se espalham. Com um monorepo Turborepo, eslint e tsconfig ficam compartilhados em packages, o cache do turbo evita rebuildar apps que não mudaram, e o --filter permite deploy por app.
Nesta página
Quando você cria apps sozinho, os repositórios se multiplicam sem parar. Um app, um site, mais um app... e lá está você copiando e colando a configuração do eslint pela quinta vez. Eu juntei tudo isso num único monorepo.
O problema de verdade são as configurações espalhadas
Com muitos repositórios, o que mais dói não é o código, são as configurações.
- Copiar eslint, prettier e tsconfig para cada repositório
- Mudar uma regra significa percorrer todos eles corrigindo
- UI e utils compartilhados são pequenos demais para publicar no npm
O monorepo transforma isso em compartilhamento num único lugar.
Estrutura básica
apps/
├── web/ # 랜딩
├── blog/ # 이 블로그
├── wave/ # 오늘의 파도
└── ...
packages/
├── eslint-config/ # 공용 eslint
└── typescript-config/ # 공용 tsconfig
apps/* são os artefatos de deploy reais, e packages/* são as configurações e o código que os apps compartilham. O tsconfig.json de cada app só herda, assim:
{ "extends": "@repo/typescript-config/nextjs.json" }
Agora as regras são corrigidas num único lugar: packages.
O cache do turbo é o ponto-chave
A verdadeira arma do Turborepo é o cache. Se as entradas de uma tarefa (fontes e configurações) não mudaram, o resultado anterior é reutilizado como está.
turbo run build # 전체 빌드(바뀐 것만 실제로 돎)
turbo run build --filter=blog # blog 앱만
Basta declarar as dependências entre tarefas e as saídas no turbo.json.
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": [".next/**"] }
}
}
A partir do segundo build, ele termina em poucos segundos com "FULL TURBO".
Deploy por app
Mesmo num único repositório, o deploy fica separado por app. Com Docker, o turbo prune recorta apenas a subárvore daquele app, deixando a imagem leve.
turbo prune blog --docker # blog + 내부 의존성만 남긴 out/ 생성
Este blog também foi recortado assim e subiu com Docker num mini PC. Essa história eu conto no post sobre self-hosting.
Resumo
apps/*= artefatos de deploy,packages/*= configurações compartilhadas- tsconfig e eslint gerenciados num único lugar via herança
- O cache do
turboevita rebuildar apps que não mudaram - Deploy por app com
--filtereprune
Se você toca vários produtos sozinho, o monorepo não é luxo, é ferramenta de sobrevivência.
Perguntas frequentes
A partir de quantos apps o monorepo compensa?
Já com mais de 2 apps, se surgem configurações compartilhadas (eslint, tsconfig, UI), compensa. O ponto central é corrigir a configuração num único lugar e refletir em todos os apps.
O build não fica mais lento?
Pelo contrário, fica mais rápido. O turbo faz cache do resultado das tarefas cujas entradas não mudaram e só rebuilda os apps que mudaram.
Artigos relacionados
- 💻 Dev
Quando um bucket tem dois donos, ganha quem fez apply por último
Adicionei uma regra de lifecycle no S3 e o terraform apply falhou. A causa: duas resources eram donas, cada uma por conta própria, da configuração de lifecycle do mesmo bucket. O lifecycle do S3 não funciona por regra, e sim por documento inteiro, então o último vencedor apaga em silêncio as regras do outro.
- 💻 Dev
Os testes estavam verdes, mas nenhuma notificação tinha sido enviada
O código que enfileirava os jobs falhava sempre, desde o primeiro dia. O erro era engolido, e os testes seguiam verdes graças aos mocks. A história de como um único caractere de dois-pontos matou três funcionalidades em silêncio.
- 💻 Dev
Chegou um alerta dizendo que o banco tinha caído. O banco nunca caiu
Em um único dia acumularam-se quatro alertas CRITICAL. 504, P2028 do Prisma, 500 no admin e 'serviço DATABASE fora do ar'. Abri primeiro as métricas do RDS: durante 21 horas seguidas, a CPU não passou de 19,7%. O lento não era o banco, eram as idas e voltas atravessando o Atlântico vinte e cinco vezes - e o alerta de 'fora do ar' foi o próprio health check que o fabricou.