Pular para o conteúdo
← Voltar para o Skalablog

Artigo publicado

Como usar micro frontends com Module Federation?

Engenharia de SoftwareNext.js

Micro frontends com Module Federation permitem que aplicações independentes exponham componentes que outras aplicações consomem em tempo real, sem novo deploy do host. Neste guia, você aprende a configurar host e remotes com Vite e o vite-plugin-federation, integrar React e Vue e decidir entre micro frontends e monorepo.

O que são micro frontends e quando eles fazem sentido

Micro frontends são pequenas aplicações front-end independentes, cada uma com seu repositório, build e ciclo de deploy, que um aplicativo central — o host — consome em tempo de execução. Eles lembram microsserviços no nome, mas resolvem um problema diferente: compartilhar interface, não lógica de negócio.

O caso de uso clássico é uma dashboard com barra lateral: o menu de relatórios pode ser um micro frontend, o de financeiro outro, e o de usuários um terceiro. Cada um pode usar uma stack diferente — React, Vue ou Angular — porque o que trafega entre host e remote é JavaScript exposto, não código-fonte compartilhado.

O instrutor do vídeo relata um caso real: uma dashboard imensa, com código antigo e sem ninguém que soubesse mantê-lo. A saída foi isolar cada feature nova em um micro frontend, com repositório e CI próprios, sem tocar no legado. Esse é o cenário onde a abordagem brilha: injetar algo novo dentro de algo velho.

Como o Module Federation funciona com o Vite

O Module Federation é um plugin do Webpack criado para permitir que múltiplas builds independentes exponham módulos entre si. O problema: o Vite não usa Webpack, e sim Rollup. A ponte é o vite-plugin-federation, que implementa o mesmo conceito para Vite e Rollup.

No remote, a configuração tem três partes essenciais:

  • name: o identificador do micro frontend, sem espaços;
  • exposes: tudo que você quer compartilhar — um botão isolado, um componente do design system ou a aplicação inteira;
  • shared: as bibliotecas que o código exposto precisa, como React ou Vue, para o plugin não instanciar duas cópias em runtime.

Ao rodar npm run build e depois npm run preview, o plugin gera o arquivo remoteEntry.js dentro de dist/assets. Esse arquivo contém tudo que foi exposto, e é nele que o host vai apontar. Detalhe importante do fluxo com Vite: o modo dev não serve o remoteEntry — você precisa de build + preview durante o desenvolvimento.

Passo a passo: host e remotes com React e Vite

O setup mínimo usa três projetos criados com a CLI do Vite com React e TypeScript: dois remotes e um host. No remote, instale o plugin, configure name, filename (remoteEntry.js), exposes e shared, e adicione ajustes no build do vite.config que evitam erros de top-level await:

ts build: { modulePreload: false, target: 'esnext', minify: false, cssCodeSplit: false, }

No host, instale o mesmo plugin e, além de name e shared, declare o array remotes, apontando cada micro frontend para a URL do seu remoteEntry:

ts remotes: { remoteOne: '[link removed] }

A partir daí, o host importa Button from 'remoteOne/Button' e o componente renderiza como se fosse local. O campo shared precisa listar as mesmas libs no remote e no host — é ele que garante uma única instância do React em execução. Uma observação prática do vídeo: ao consumir o componente Vue no host, foi preciso remover o StrictMode do React para o exemplo funcionar.

Renderizando uma aplicação Vue dentro do React

Uma aplicação Vue pode ser exposta como remote e consumida por um host React, mas não com import direto: um componente Vue não é um componente React. O caminho é criar uma função wrapper no remote que usa createApp do Vue e monta o componente em um elemento HTML recebido como parâmetro.

ts import { createApp } from 'vue' import HelloWorld from './HelloWorld.vue'

export function mount(el: Element) { createApp(HelloWorld).mount(el) }

Esse wrapper entra no exposes do remote. No host React, você cria uma div com useRef e chama a função dentro de um useEffect, passando ref.current como elemento. O host também precisa ter Vue instalado como dependência e listado no shared.

O mesmo padrão vale para Angular ou qualquer outra framework: quem entende o componente é o remote, que o monta num elemento; o host só fornece o contêiner. Para um remote React consumido em outro lugar, a função usaria createRoot e .render(). O repositório do plugin inclui uma demo de interoperabilidade entre Vite e Webpack, útil quando a aplicação legada ainda roda no bundler antigo.

Os dois maiores problemas: tipagem fraca e versionamento

O que o host consome é um arquivo JavaScript, então o TypeScript do lado do host não conhece os módulos expostos. A tipagem forte desaparece: sem autocomplete confiável e sem controle-click para navegar até o componente. No projeto relatado no vídeo, a equipe criou arquivos de declaração manuais (remoteOne.d.ts) e depois uma biblioteca de tipagens compartilhada — mas ambas são escritas à mão e podem divergir do código real.

O segundo risco é o versionamento. Se o time do remote sobe uma alteração que quebra, o host quebra junto, porque consome o arquivo em tempo real. A mitigação usual é hospedar o remoteEntry em um bucket estático do Amazon S3 com versão no caminho, por exemplo bucket.com/1.0.1/remoteEntry.js. Assim, cada host escolhe qual versão consumir e você pode fazer rollback sem tocar no remote.

Isso também responde uma dúvida comum: os projetos não precisam estar no mesmo repositório. Basta que o remoteEntry esteja acessível ao host, e o S3 é o lugar típico para isso.

Micro frontends ou monorepo: como decidir

O monorepo é a alternativa mais próxima: um único repositório com vários projetos isolados, cada um com seu package. e suas dependências. Ferramentas como Turborepo e Nx criam essa estrutura com apps e packages compartilhados, como um package de UI com o design system usado por todas as aplicações.

A diferença fundamental é quando o código é consumido. No monorepo, o package é compilado para dentro da aplicação que o importa: tipagem forte, navegação direta ao código e um controle maior. No micro frontend, o host carrega o remoteEntry em runtime de uma URL externa, com deploy independente — e todos os trade-offs de tipagem e versão que vimos.

CritérioMicro frontendsMonorepo
RepositórioUm por remoteUm só
DeployIndependente por remoteUnificado
TipagemFraca, declarações manuaisForte, código local
Stack por projetoLivre (React, Vue, Angular)Livre, mas no mesmo repo
Limite práticoTimes grandes e legadosTime pequeno a médio

A regra prática do vídeo é simples de aplicar. Time grande, onde um repositório único ficaria insustentável? Micro frontends. Aplicação legada em que você precisa injetar uma feature nova? Micro frontends. Projeto do zero com um time de cinco ou seis pessoas? Monorepo, com velocidade de CI melhor e DX superior. O próprio instrutor relata que um monorepo muito grande ficou lento até para salvar arquivos — o tamanho do repositório é o limite real dessa abordagem.

Module Federation com Next.js: por que evitar em produção

Existe um plugin de Module Federation para Next.js, mas a própria documentação dele reconhece a dificuldade: o remoteEntry é um artefato estático, concebido para SPAs, e o modelo de server components e SSR do Next caminha na direção oposta a essa arquitetura. A recomendação direta do vídeo é não usar Module Federation com Next.js em produção.

Isso não significa que SPAs com Vite estejam mortas. Para dashboards, painéis internos e aplicações atrás de login — exatamente o caso de uso de micro frontends — Vite com Module Federation continua uma escolha sólida. O Next amplia o leque de problemas que você consegue resolver; ele não substitui o Vite em todos os cenários.

Perguntas frequentes

  • Preciso do Webpack para usar Module Federation? Não. O Module Federation nasceu como plugin do Webpack, mas com Vite você usa o vite-plugin-federation, que implementa o mesmo conceito sobre Rollup. A configuração muda de formato, mas os pilares são os mesmos: name, exposes, shared e remotes.
  • Os host e os remotes precisam estar no mesmo repositório? Não. O que importa é o arquivo remoteEntry.js estar acessível ao host, de preferência em hospedagem estática como o S3. Times diferentes podem trabalhar em repositórios completamente separados.
  • Posso consumir um micro frontend Vue dentro de uma aplicação React? Sim, mas não com import direto. Você cria no remote uma função que monta o componente Vue em um elemento HTML com createApp, expõe essa função e a chama no host dentro de um useEffect, passando a referência de uma div.
  • Por que a tipagem TypeScript é fraca em micro frontends? Porque o host consome um arquivo JavaScript gerado no build, sem tipos. As soluções usuais — arquivos .d.ts escritos à mão ou uma lib de tipagens compartilhada — funcionam, mas não são geradas automaticamente e podem divergir do código real.
  • Como atualizar um micro frontend sem fazer deploy do host? É o comportamento padrão: o host carrega o remoteEntry em runtime, então basta o remote publicar uma nova versão. Para controle fino, versionar o caminho do arquivo no S3 permite que cada host decida qual versão consumir.

Do vídeo para o artigo: o mesmo isolamento, outro formato

Essa aula de 50 minutos comprime uma decisão arquitetural inteira — host, remotes, shared, S3, monorepo — em uma sequência que vale mais lida do que revista de trás para frente. Se você também tem conhecimento nesse formato, uma aula gravada, uma live técnica ou uma entrevista no YouTube, transformá-lo em texto é a forma de torná-lo encontrável e citável.

O Skala Blog faz exatamente esse caminho: você cola a URL do vídeo, o conteúdo é transcrito e vira um artigo estruturado, pronto para revisão e publicação. O que você já explicou uma vez pode ficar disponível para quem procura.

Source video