Monorepositório com JavaScript: organização de código e melhores práticas
O desenvolvimento moderno em JavaScript (Node.js) frequentemente enfrenta o problema de gerenciamento de código em grandes projetos. Quando o número de microsserviços, bibliotecas e aplicações cresce, os repositórios multimodulares tradicionais (Polyrepo) começam a criar caos: duplicação de configurações, dificuldades com sincronização de versões e CI/CD lento. A solução é o monorepositório (monorepo). Neste artigo, vamos analisar como organizar o código em um monorepositório em JavaScript, quais ferramentas usar e como evitar erros típicos.
O que é um monorepositório e para que serve?
Monorepositório é uma abordagem onde todo o código do projeto (várias aplicações, bibliotecas, serviços) é armazenado em um único repositório. Ao contrário do Polyrepo, onde cada componente vive em seu próprio repositório Git, o monorepo une tudo em uma estrutura única.
Vantagens do monorepositório para JavaScript:
- Versão única de dependências — todos os pacotes usam as mesmas versões de bibliotecas, eliminando conflitos.
- Reutilização de código — utilitários e componentes compartilhados são facilmente importados entre subprojetos sem publicação no npm.
- Commits atômicos — alterações em vários pacotes podem ser feitas em um único commit, simplificando revisão e reversão.
- CI/CD simplificado — um único pipeline para todo o projeto, cache de builds e testes.
No entanto, o monorepositório também tem desvantagens: exige disciplina rigorosa na organização do código e escolha correta de ferramentas. A seguir, veremos como organizar a estrutura e quais ferramentas usar.
Ferramentas para gerenciar monorepositório em Node.js
O ecossistema JavaScript oferece várias ferramentas maduras para trabalhar com monorepo. Vamos considerar as três mais populares:
1. Lerna
Ferramenta clássica que foi o padrão por muito tempo. Lerna gerencia publicação de pacotes, versionamento e execução de scripts em todos os pacotes. Exemplo de configuração lerna.json:
{ "version": "independent", "packages": ["packages/*"], "npmClient": "yarn"}O comando lerna bootstrap instala dependências para todos os pacotes e os vincula entre si.
2. Nx (Nrwl)
Ferramenta mais moderna e poderosa com sistema avançado de cache, grafos de dependências e geradores de código. Nx suporta não apenas JavaScript, mas também TypeScript, Angular, React, Next.js. Exemplo de comando para criar uma biblioteca:
npx nx generate @nrwl/node:library my-lib --directory=sharedNx analisa automaticamente as dependências e reconstrói apenas os pacotes alterados.
3. Turborepo
Criado pela Vercel, Turborepo foca na velocidade de build e simplicidade. Ele usa cache inteligente e execução paralela de tarefas. Exemplo de turbo.json:
{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "test": { "dependsOn": ["build"], "outputs": [] } }}Turborepo é ideal para projetos com grande número de pacotes onde a velocidade do CI é importante.
Organização da estrutura do projeto em monorepositório
Uma estrutura de pastas correta é a base de um monorepo bem-sucedido. Vamos considerar uma estrutura típica para um projeto Node.js:
my-monorepo/├── packages/│ ├── shared-utils/ # Utilitários compartilhados│ │ ├── src/│ │ │ └── index.js│ │ └── package.json│ ├── api-gateway/ # API Gateway│ │ ├── src/│ │ │ └── server.js│ │ └── package.json│ └── web-app/ # Aplicação web (React/Vue)│ ├── src/│ │ └── App.js│ └── package.json├── tools/ # Scripts e configurações