Micro Frontends: Como Escalar Aplicacoes Frontend Com Arquitetura Modular
Olá HaWkers, se você trabalha em uma empresa com times grandes de frontend ou em um monolito que está difícil de manter, provavelmente já ouviu falar de micro frontends. Essa arquitetura promete trazer para o frontend os mesmos benefícios que microserviços trouxeram para o backend.
Mas será que vale a pena? E como implementar de forma que não vire um pesadelo? Vamos explorar isso em profundidade.
O Que São Micro Frontends
Micro frontends é uma arquitetura onde uma aplicação web é dividida em partes menores e independentes, cada uma desenvolvida, testada e implantada separadamente.
Analogia simples:
- Monolito frontend = Uma loja onde todos os departamentos compartilham o mesmo caixa
- Micro frontends = Um shopping onde cada loja opera independentemente
Características principais:
- Independência de deploy - Cada parte pode ser atualizada sem afetar as outras
- Autonomia de time - Times diferentes podem trabalhar em partes diferentes
- Tecnologia agnóstica - Cada parte pode usar tecnologias diferentes
- Isolamento de falhas - Problemas em uma parte não derrubam o sistema inteiro
🏗️ Contexto: O termo foi cunhado em 2016, mas ganhou tração a partir de 2019 quando empresas como IKEA, Spotify e DAZN compartilharam suas experiências.
Quando Usar Micro Frontends
Antes de adotar essa arquitetura, você precisa ter certeza que ela resolve um problema real:
Sinais de Que Você Precisa
Indicadores organizacionais:
- Múltiplos times trabalhando no mesmo frontend
- Conflitos constantes de merge
- Deploy bloqueado esperando outras features
- Tempo de build/teste muito longo
- Dificuldade de onboarding de novos devs
Indicadores técnicos:
- Aplicação com centenas de milhares de linhas de código
- Bundle size muito grande
- Performance de desenvolvimento degradada
- Testes lentos demais
Sinais de Que Você NÃO Precisa
Quando evitar:
- Time pequeno (menos de 10 desenvolvedores frontend)
- Aplicação de tamanho médio
- Domínio de negócio fortemente acoplado
- Startup em fase inicial
- Time sem experiência em arquitetura distribuída
Regra de ouro: Se você não tem problemas claros de escala ou organização, micro frontends vai adicionar complexidade sem benefício.
Padrões de Implementação
Existem várias formas de implementar micro frontends. Vamos ver as principais:
1. Module Federation (Webpack 5+)
A abordagem mais moderna e popular atualmente:
// webpack.config.js do Host (Shell)
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
// Carrega micro frontend de carrinho de outro servidor
cartMfe: 'cartMfe@http://localhost:3001/remoteEntry.js',
// Carrega micro frontend de produtos
productsMfe: 'productsMfe@http://localhost:3002/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};
// webpack.config.js do Micro Frontend de Carrinho
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'cartMfe',
filename: 'remoteEntry.js',
exposes: {
'./Cart': './src/components/Cart',
'./CartButton': './src/components/CartButton',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};Uso no Host:
// App.jsx no Host
import React, { Suspense } from 'react';
// Importação dinâmica do micro frontend remoto
const RemoteCart = React.lazy(() => import('cartMfe/Cart'));
const RemoteProducts = React.lazy(() => import('productsMfe/ProductList'));
function App() {
return (
<div className="app">
<header>Minha Loja</header>
<main>
<Suspense fallback={<div>Carregando produtos...</div>}>
<RemoteProducts />
</Suspense>
</main>
<aside>
<Suspense fallback={<div>Carregando carrinho...</div>}>
<RemoteCart />
</Suspense>
</aside>
</div>
);
}2. Single-SPA
Framework dedicado para orquestrar micro frontends:
// root-config.js
import { registerApplication, start } from 'single-spa';
// Registra micro frontend de navegação
registerApplication({
name: '@myorg/navbar',
app: () => System.import('@myorg/navbar'),
activeWhen: ['/'],
});
// Registra micro frontend de produtos (ativo em /products)
registerApplication({
name: '@myorg/products',
app: () => System.import('@myorg/products'),
activeWhen: ['/products'],
});
// Registra micro frontend de checkout (ativo em /checkout)
registerApplication({
name: '@myorg/checkout',
app: () => System.import('@myorg/checkout'),
activeWhen: ['/checkout'],
});
start();3. iFrames (Abordagem Simples)
Para isolamento total quando necessário:
// Componente wrapper para micro frontend via iframe
function MicroFrontendFrame({ src, title, height = '600px' }) {
return (
<iframe
src={src}
title={title}
style={{
width: '100%',
height,
border: 'none',
}}
sandbox="allow-scripts allow-same-origin allow-forms"
/>
);
}
// Uso
<MicroFrontendFrame
src="https://checkout.myapp.com"
title="Checkout"
height="800px"
/>;
Comunicação Entre Micro Frontends
Um dos maiores desafios é fazer os micro frontends se comunicarem:
Event Bus
Padrão simples e eficaz:
// eventBus.js - Compartilhado entre todos os MFEs
class EventBus {
constructor() {
this.events = {};
}
subscribe(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
// Retorna função para unsubscribe
return () => {
this.events[event] = this.events[event].filter((cb) => cb !== callback);
};
}
publish(event, data) {
if (this.events[event]) {
this.events[event].forEach((callback) => callback(data));
}
}
}
// Singleton global
window.eventBus = window.eventBus || new EventBus();
export default window.eventBus;Uso:
// No MFE de Produtos
import eventBus from '@shared/eventBus';
function ProductCard({ product }) {
const addToCart = () => {
eventBus.publish('cart:add', {
productId: product.id,
quantity: 1,
});
};
return (
<div className="product">
<h3>{product.name}</h3>
<button onClick={addToCart}>Adicionar ao Carrinho</button>
</div>
);
}
// No MFE de Carrinho
import eventBus from '@shared/eventBus';
function Cart() {
const [items, setItems] = useState([]);
useEffect(() => {
const unsubscribe = eventBus.subscribe('cart:add', (data) => {
setItems((prev) => [...prev, data]);
});
return unsubscribe;
}, []);
return <div>{/* Renderiza itens */}</div>;
}Custom Events (Browser Native)
Alternativa sem dependências:
// Publicar
window.dispatchEvent(
new CustomEvent('cart:updated', {
detail: { items: cartItems },
})
);
// Subscrever
window.addEventListener('cart:updated', (event) => {
console.log('Carrinho atualizado:', event.detail.items);
});
Desafios e Armadilhas
Micro frontends trazem complexidade. Esteja preparado:
1. Consistência de UI
Problema: Cada MFE pode ter estilos diferentes.
Solução: Design System compartilhado
// @myorg/design-system - Pacote npm interno
export { Button } from './components/Button';
export { Card } from './components/Card';
export { theme } from './theme';
export { GlobalStyles } from './GlobalStyles';2. Duplicação de Dependências
Problema: React carregado múltiplas vezes.
Solução: Shared dependencies no Module Federation
shared: {
react: {
singleton: true,
requiredVersion: '^18.0.0',
eager: true
}
}3. Performance
Problema: Múltiplas requisições de rede.
Soluções:
- Prefetch de MFEs críticos
- Service workers para cache
- CDN compartilhado
4. Testes End-to-End
Problema: Como testar a aplicação completa?
Solução: Ambiente de integração dedicado
# docker-compose.integration.yml
services:
shell:
build: ./packages/shell
ports:
- '3000:3000'
cart-mfe:
build: ./packages/cart
ports:
- '3001:3001'
products-mfe:
build: ./packages/products
ports:
- '3002:3002'
Ferramentas do Ecossistema
O ecossistema evoluiu bastante em 2024-2025:
Build e Bundling
| Ferramenta | Uso | Suporte MFE |
|---|---|---|
| Webpack 5 | Module Federation nativo | Excelente |
| Vite | vite-plugin-federation | Bom |
| Rspack | Module Federation | Excelente |
| esbuild | Customização necessária | Básico |
Frameworks de Orquestração
| Framework | Complexidade | Maturidade |
|---|---|---|
| Single-SPA | Alta | Alta |
| Module Federation | Média | Alta |
| Qiankun | Média | Média |
| Luigi (SAP) | Alta | Alta |
Monorepo Tools
Para gerenciar múltiplos MFEs:
- Nx - Mais popular, ótimo suporte a MFE
- Turborepo - Performance, integração Vercel
- Lerna - Clássico, menos features
- pnpm workspaces - Leve e eficiente
Conclusão
Micro frontends são uma ferramenta poderosa para escalar times e aplicações grandes. Mas como toda arquitetura distribuída, trazem complexidade que precisa ser justificada.
Use se:
- Tem múltiplos times independentes
- Aplicação genuinamente grande
- Problemas claros de escala
- Time experiente em sistemas distribuídos
Evite se:
- Time pequeno ou médio
- Aplicação de tamanho normal
- Buscando solução para problemas organizacionais
- Sem experiência em arquitetura distribuída
Se você decidir implementar, comece pequeno: extraia um MFE, aprenda com os desafios, e escale gradualmente. A pior coisa que você pode fazer é migrar tudo de uma vez.
Para complementar seu conhecimento em arquiteturas modernas de frontend, recomendo conferir o artigo Vite vs Webpack em 2025 onde você vai entender as ferramentas de build que suportam essas arquiteturas.
Bora pra cima! 🦅
💻 Domine JavaScript de Verdade
O conhecimento que você adquiriu neste artigo é só o começo. Há técnicas, padrões e práticas que transformam desenvolvedores iniciantes em profissionais requisitados.
Invista no Seu Futuro
Preparei um material completo para você dominar JavaScript:
Formas de pagamento:
- 1x de R$9,90 sem juros
- ou R$9,90 à vista

