Publicado em
- 4 minutos de leitura
Micro Frontends no Angular: Native Federation e Web Components
Quem trabalha com Micro Frontends no Angular enfrentou uma mudança importante com a chegada do novo pipeline de build do Angular CLI.
O framework trocou o Webpack pelo ApplicationBuilder, que junta esbuild para gerar o bundle de produção e Vite para o servidor de desenvolvimento.
O tempo de build caiu bastante, mas surgiu um problema prático: o Webpack Module Federation clássico parou de funcionar de forma nativa. Para resolver isso, duas opções se destacam hoje: o Native Federation e os Web Components com Angular Elements. Neste artigo, vamos ver o funcionamento de cada uma, o código de setup e quando escolher cada caminho.
O problema do Webpack no Angular moderno
Durante muito tempo, o Module Federation do Webpack foi a escolha padrão para carregar remotes em tempo de execução. Ele cuidava de carregar o código sob demanda e evitava baixar bibliotecas repetidas entre times diferentes.
O detalhe é que essa solução depende de plugins internos do Webpack.
Quando o Angular adotou o ApplicationBuilder com esbuild, manter o Webpack passou a exigir builders customizados, como o @angular-builders/custom-webpack.
Na prática, isso traz dores de cabeça reais:
- O build fica bem mais lento do que com
esbuild. - Recursos novos do Angular, como hidratação parcial e SSR moderno, ficam difíceis de configurar.
- Você fica preso a ferramentas antigas só para manter o roteamento de Micro Frontends funcionando.
Por isso, buscar uma alternativa que funcione direto com esbuild se tornou prioridade.
Como funciona o Native Federation
Criado por Manfred Steyer e mantido pela comunidade, o Native Federation resolve esse problema usando padrões nativos da web. Em vez de depender de código gerado por um bundler específico, ele usa ECMAScript Modules (ESM) e Import Maps do próprio navegador.
Isso significa que o Native Federation funciona tanto com esbuild quanto com Vite, Rollup ou qualquer outra ferramenta moderna.
O fluxo de funcionamento é bem simples:
- O Shell lê o arquivo
remoteEntry.jsonde cada aplicação remote para saber quais módulos e versões estão disponíveis. - O Native Federation processa as dependências e monta um Import Map no navegador para não baixar pacotes como
@angular/coreerxjsduas vezes. - O Angular Router carrega o componente remoto com
loadComponentouloadChildren, exatamente como faz com lazy loading comum.
Como usa ESM puro, o Native Federation funciona sem problemas com blocos @defer e SSR.
Configurando Shell e Remote com Native Federation
Para configurar o projeto, usamos o pacote @angular-architects/native-federation.
No Shell, o arquivo federation.config.js define quais dependências devem ser tratadas como singletons compartilhados:
// federation.config.js (Shell)
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config')
module.exports = withNativeFederation({
shared: {
...shareAll({
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
})
}
})
No roteamento do Shell, usamos a função loadRemoteModule para carregar a tela remota:
// app.routes.ts (Shell)
import { Routes } from '@angular/router'
import { loadRemoteModule } from '@angular-architects/native-federation'
export const routes: Routes = [
{
path: 'checkout',
loadComponent: () =>
loadRemoteModule({
remoteEntry: 'http://localhost:4201/remoteEntry.json',
exposedModule: './Component'
}).then((m) => m.CheckoutComponent)
}
]
Já no Remote, expomos o componente que o Shell vai carregar:
// federation.config.js (Remote - Checkout)
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config')
module.exports = withNativeFederation({
name: 'checkout',
exposes: {
'./Component': './src/app/checkout/checkout.component.ts'
},
shared: {
...shareAll({
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
})
}
})
Com o handshake de versões ativado, se o Shell e o Remote usarem a mesma versão do Angular, apenas uma cópia do runtime fica na memória.
Quando usar Web Components com Angular Elements
O Native Federation funciona muito bem quando todos os times usam Angular e mantêm versões próximas do framework. Mas existem cenários onde isso não acontece: times trabalhando com versões incompatíveis do Angular ou até misturando Angular com React.
Nesses casos, os Web Components com @angular/elements são a melhor opção de blindagem.
O Angular Elements transforma um componente comum em um Custom Element nativo do navegador, isolado com Shadow DOM.
// bootstrap-element.ts
import { createCustomElement } from '@angular/elements'
import { createApplication } from '@angular/platform-browser'
import { ProductCardComponent } from './product-card.component'
createApplication().then((appRef) => {
const cardElement = createCustomElement(ProductCardComponent, {
injector: appRef.injector
})
customElements.define('app-product-card', cardElement)
})
A grande vantagem é o isolamento de CSS via Shadow DOM e a liberdade de rodar qualquer versão sem conflitos de variáveis globais. O tradeoff principal é o tamanho final do bundle: cada Custom Element traz seu próprio runtime, o que aumenta o volume de dados baixados pelo usuário.
Comparativo de decisão técnica
A tabela abaixo resume as principais características de cada abordagem:
| Critério | Webpack Module Federation | Native Federation | Angular Elements |
|---|---|---|---|
| Compatível com esbuild e Vite | — | ✓ | ✓ |
| Compartilha Singletons na memória | ✓ | ✓ | — |
| Isolamento de estilos com Shadow DOM | — | — | ✓ |
| Suporte a múltiplos frameworks | — | — | ✓ |
| Funciona com SSR e @defer | — | ✓ | — |
| Sem plugins customizados de build | — | ✓ | ✓ |
Guia rápido para o dia a dia
Para decidir o caminho no seu projeto, siga este roteiro prático:
- Escolha Native Federation para projetos Angular padronizados: Se os times compartilham a mesma versão do Angular, o Native Federation dá o melhor resultado em velocidade de build e uso eficiente de memória.
- Use Web Components para legados e exceções: Se uma funcionalidade precisa ficar em uma versão antiga do Angular ou em outro framework, encapsule essa parte específica como Custom Element.
- Mantenha controle de versões com Monorepo: Ferramentas como o Nx ajudam a garantir que bibliotecas compartilhadas e design systems fiquem alinhados entre o Shell e os Remotes.
Conclusão
O ecossistema de Micro Frontends no Angular não depende mais de soluções presas ao Webpack.
Com o Native Federation, você aproveita a velocidade do esbuild usando padrões abertos como Import Maps e ESM.
Ao mesmo tempo, os Web Components continuam sendo a ferramenta certa quando o foco principal é o isolamento total entre equipes. Entender esses tradeoffs ajuda a escolher a arquitetura mais simples e sustentável para o seu time.
Entre na nossa comunidade!
Receba novos posts, novidades do ecossistema Angular e muito mais.
Sobre o autor