Cinco squads no mesmo repositório frontend produzem conflito de merge diário, build que cresce a cada sprint e release travado por time que não toca na sua feature. Micro-frontends separam a aplicação em unidades que cada squad publica sozinho. A troca aparece depois da adoção: runtime, deploy e debug ganham peças novas.
O problema que a arquitetura ataca
Micro-frontends se pagam com três condições simultâneas: 3+ times no mesmo frontend, release independente por squad e sobreposição de código pequena entre eles. Cam Jackson, no artigo Micro Frontends (martinfowler.com, 2019), descreve o objetivo como aumentar a capacidade de times que trabalham no mesmo produto, e o custo aparece justamente na manutenção da coerência entre peças publicadas em velocidades diferentes.
Um squad de dois times com fronteira de domínio clara paga a infraestrutura de micro-frontends e não recebe velocidade de volta. Meça o tempo entre abrir o PR e publicar em produção antes de assinar qualquer migração.
Três formas de compor a página
Integração em build: Module Federation
O Module Federation do Webpack carrega módulos de outra aplicação em runtime. Cada micro-frontend é uma aplicação standalone que exporta um remote entry, e o shell decide qual entra em cada rota. Rspack e o projeto Module Federation independente mantêm o mesmo conceito.
// webpack.config.js: shell
new ModuleFederationPlugin({
name: 'shell',
remotes: {
checkout: 'checkout@https://checkout.example.com/remoteEntry.js',
catalog: 'catalog@https://catalog.example.com/remoteEntry.js',
},
})
Integração em runtime com iframe
iframe isola estilos, JavaScript e ciclo de vida por completo. A comunicação vira postMessage, e o preço aparece em acessibilidade, SEO e compartilhamento de sessão entre as partes.
Composição no servidor: SSI e ESI
O servidor monta a página antes de enviar e o cliente recebe HTML pronto. A orquestração sai do browser, e a exigência passa a ser infraestrutura de include mais um contrato de HTML claro entre times.
Estrutura de repositórios na prática
shell-app/ # Monta a página e o layout base
├── src/
│ ├── Header.tsx # Compartilhado entre todos
│ ├── Footer.tsx # Compartilhado entre todos
│ └── MicroApp.tsx # Loader dos micro-frontends
│
checkout/ # Squad de checkout
├── src/
│ ├── Checkout.tsx
│ ├── Payment.tsx
│ └── Shipping.tsx
│
catalog/ # Squad de catálogo
├── src/
│ ├── ProductList.tsx
│ └── ProductDetail.tsx
Custos que aparecem na operação
- Comunicação: dado compartilhado exige event bus, store no shell ou contrato de props. Sem isso, cada squad guarda a própria cópia do carrinho.
- Estilo: design system em pacote versionado é pré-requisito. Tokens e componentes base saem de um lugar só.
- Performance: cada bundle extra custa requests HTTP e parse de JS. O shell cuida de preload e de lazy load por rota.
- Debug: stack trace que atravessa dois bundles pede dois times no mesmo call.
- Deploy: dependência entre squads devolve o deploy coordenado que a arquitetura prometia eliminar.
Times que chegam ao quinto custo descobrem que a independência de deploy sobrevive só enquanto os contratos entre as peças permanecem estáveis.
Quando adotar
Adote quando três ou mais squads publicam no mesmo produto sem coordenação de release, o gargalo de merge já aparece em métrica e cada time consegue explicar a fronteira de domínio da própria fatia. A velocidade de time ganha espaço; o custo de infraestrutura entra no orçamento do mesmo jeito.
Quando ficar no monólito
Dois squads ou menos, features que se sobrepõem e release compartilhado pedem monólito modular com pastas e módulos por domínio. Arquitetura nova não conserta processo de time quebrado, e o monólito bem dividido publica com a mesma rapidez.
Referências
- Micro Frontends, Cam Jackson (martinfowler.com, 2019)
- Webpack: Module Federation
- Module Federation, documentação do projeto independente
Curtiu o conteúdo?
Construo produtos web e soluções com IA do jeito certo — arquitetura sólida, código sustentável e entrega real.
Vamos conversar