Voltar ao blog
monorepoTurborepoViteworkspacesbuildCIfront-end

Monorepos e tooling frontend: Vite, Turborepo e builds que escalam

2026-10-01
Monorepos e tooling frontend: Vite, Turborepo e builds que escalam

Conforme uma empresa cresce, o código se multiplica: o app web, o painel administrativo, o site de marketing, a biblioteca de componentes, os utilitários compartilhados. A pergunta que toda equipe acaba enfrentando é como organizar tudo isso. Um repositório para cada coisa, com o custo de sincronizar mudanças entre eles? Ou um único repositório que abriga tudo? Essa segunda opção, o monorepo, virou padrão em muitos times de frontend justamente porque resolve o problema de compartilhar código sem a dor de coordenar dezenas de repositórios.

Mas monorepo não é uma bala de prata, e adotá-lo sem o tooling certo troca um conjunto de problemas por outro. Este guia explica o que é um monorepo de verdade, como workspaces, cache de build e CI seletivo o tornam rápido, como versionar pacotes internos e, com igual importância, quando não vale a pena usá-lo.

O que é (e o que não é) um monorepo

Um monorepo é um único repositório que contém múltiplos projetos ou pacotes relacionados, com um histórico de versionamento compartilhado. Vale desfazer duas confusões comuns:

  • Não é uma "pasta gigante de código bagunçado". Um monorepo bem estruturado tem limites claros entre pacotes, cada um com sua responsabilidade e suas dependências explícitas.
  • Não é o mesmo que monolito. Monolito é sobre arquitetura de execução (um único artefato que roda junto). Monorepo é sobre organização de código. Dá para ter um monorepo que produz vários serviços independentes, e um monolito espalhado por vários repositórios.

O valor central é o código compartilhado sem fricção: uma biblioteca de componentes ou um pacote de utilitários vive ao lado de quem o consome, e uma mudança atravessa tudo em um único commit, com uma única revisão.

Workspaces: a base da organização

A peça fundamental é o conceito de workspaces, suportado pelos gerenciadores de pacote modernos. Um workspace declara que aquele repositório contém vários pacotes e permite que eles se refiram uns aos outros como se fossem dependências normais, sem publicar nada.

Uma estrutura típica separa aplicações de bibliotecas compartilhadas:

meu-monorepo/
├── apps/
│   ├── web/          # aplicação principal
│   └── admin/        # painel administrativo
├── packages/
│   ├── ui/           # biblioteca de componentes
│   ├── config/       # configs compartilhadas (lint, tsconfig)
│   └── utils/        # utilitários comuns
└── package.json      # define os workspaces

Com isso, o apps/web importa @empresa/ui diretamente, e qualquer alteração no pacote de UI já reflete no app, sem passos de publicação. As dependências são instaladas de forma unificada, evitando duplicação e conflitos de versão entre os projetos.

O problema que o tooling resolve: velocidade

Aqui está o ponto que separa um monorepo bom de um insuportável. Sem ferramentas adequadas, um monorepo grande fica lento: qualquer mudança dispara a reconstrução e o teste de tudo, mesmo do que não foi afetado. É aí que entram orquestradores de build como o Turborepo (e alternativas no mesmo espírito), que introduzem dois superpoderes.

Cache de build

O primeiro é o cache. A ferramenta entende o grafo de dependências entre os pacotes e guarda o resultado de cada tarefa (build, teste, lint). Se nada mudou na entrada de uma tarefa, ela não roda de novo: o resultado sai do cache, instantaneamente. Rodar o build duas vezes seguidas, sem mudanças, deixa de custar minutos e passa a custar segundos.

Melhor ainda, o cache pode ser remoto e compartilhado pelo time e pela CI. Se um colega (ou o pipeline) já construiu determinado pacote com aquele mesmo estado, a sua máquina reaproveita o resultado, sem reconstruir localmente. O trabalho é feito uma vez e reusado por todos.

CI seletivo (affected)

O segundo superpoder é rodar apenas o que foi afetado. Ao conhecer o grafo de dependências, a ferramenta calcula quais pacotes uma mudança realmente impacta e limita build e testes a eles. Alterar o site de marketing não precisa reconstruir e testar o painel administrativo. Em um monorepo grande, isso corta drasticamente o tempo de CI e devolve o feedback rápido que a mudança de repositório único ameaçava tirar.

Sobre as ferramentas de build de cada app, o Vite se tornou o padrão pela velocidade: servidor de desenvolvimento quase instantâneo e builds de produção otimizados. Em um monorepo, cada app pode ter seu Vite, enquanto o orquestrador coordena as tarefas entre todos os pacotes.

Versionamento de pacotes internos

Como lidar com versões quando os pacotes vivem juntos? Há duas filosofias:

Abordagem Como funciona Melhor para
Versão fixa (lockstep) Todos os pacotes sobem de versão juntos Times que publicam tudo em conjunto
Versão independente Cada pacote tem sua própria versão Bibliotecas com consumidores externos

Para pacotes puramente internos (consumidos só dentro do monorepo), muitas vezes nem é preciso versionar de forma tradicional: como tudo muda no mesmo commit, o apps/web sempre usa a versão mais recente do packages/ui. O versionamento formal, com changelog e publicação, ganha importância quando um pacote também é distribuído para fora, e aí valem os mesmos princípios de retrocompatibilidade de qualquer biblioteca pública: mudanças que quebram exigem uma nova versão maior e um aviso claro. Ferramentas de gestão de releases automatizam esse fluxo, gerando changelog a partir dos commits.

Quando NÃO usar um monorepo

Tão importante quanto saber adotar é saber recusar. Monorepo tem custos, e em vários cenários ele é a escolha errada:

  • Projetos pequenos ou isolados. Um único app sem código compartilhado não ganha nada com a complexidade de um monorepo. Um repositório simples é melhor.
  • Times totalmente independentes, com ciclos de release e stacks que não se cruzam. Se os projetos não compartilham código nem coordenação, forçá-los no mesmo repositório só adiciona atrito.
  • Sem apetite para investir em tooling. Um monorepo grande exige cache e CI seletivo para não virar um gargalo. Sem esse investimento, a lentidão come todo o benefício.
  • Necessidade de permissões muito granulares por projeto, algo que repositórios separados resolvem de forma mais natural.

A pergunta honesta é: existe código compartilhado suficiente e coordenação suficiente entre os projetos para justificar a estrutura? Se a resposta é não, repositórios separados são mais simples e igualmente válidos. Monorepo é uma resposta para um problema de escala e compartilhamento, não um objetivo em si.

Estrutura a serviço da velocidade

Um monorepo bem montado dá ao time o melhor de dois mundos: o compartilhamento de código sem a burocracia de coordenar muitos repositórios, e a velocidade de builds que só reconstroem o que mudou. A chave não é o repositório único em si, é o tooling que o torna rápido: workspaces organizando os pacotes, cache eliminando trabalho repetido e CI seletivo mantendo o feedback ágil mesmo com o código crescendo. Sem isso, o monorepo trava; com isso, ele escala.

Na ConstructorTI, ajudamos times a estruturar monorepos frontend que escalam de verdade: workspaces bem desenhados, orquestração de build com cache local e remoto, CI seletivo por pacotes afetados e uma estratégia de versionamento adequada ao seu contexto, além do julgamento honesto de quando um monorepo não é a resposta. Se os seus builds estão lentos, o código está duplicado entre projetos ou você está avaliando reorganizar os repositórios, fale com o nosso time de engenharia e saia da conversa com um plano claro de arquitetura e tooling.