Vite 6: ESM Module Federation e otimização de desempenho na prática

46 segundos.
Esse era o tempo que a equipe da Linear esperava para compilar o projeto. A cada linha de código alterada e a cada novo build, passavam-se 46 segundos. No fim de 2024, a equipe atualizou o Vite para a versão 6 e ativou o Rolldown — o tempo de build caiu para 6 segundos.
Quando vi esse dado, fiquei bastante desconfiado. Dez vezes mais rápido? Só depois de testar no meu próprio projeto percebi que o resultado não era exagero.
O Vite 6 não é uma atualização pequena que apenas muda algumas opções de configuração. A Environment API altera por completo a forma de lidar com builds para vários ambientes, a integração com o Rolldown finalmente aproxima a lógica de empacotamento de desenvolvimento e produção, e o ESM Module Federation começa a dar sinais de suporte oficial.
Projetos comuns talvez quase não percebam essas mudanças. Mas, para quem mantém uma aplicação frontend grande, trabalha com uma arquitetura de micro frontends ou simplesmente cansou do pesadelo em que tudo funciona no ambiente de desenvolvimento e quebra em produção, vale seguir até o fim.
Capítulo 1: principais novidades do Vite 6
1.1 Environment API: um novo modelo para vários ambientes
A Environment API é a mudança arquitetural mais importante do Vite 6. Mas, sendo direto, a maioria dos projetos provavelmente nunca precisará mexer nela.
Antes, o Vite considerava por padrão apenas os ambientes client e ssr. Para implantar em Cloudflare Workers, Deno ou outro runtime de edge, era preciso encontrar uma solução por conta própria. Para oferecer suporte a todos esses ambientes, autores de frameworks acabavam escrevendo uma série de hacks.
A Environment API formaliza esse processo. Agora é possível configurar assim:
// vite.config.ts
export default defineConfig({
environments: {
client: {
// Ambiente do navegador
build: {
outDir: 'dist/client'
}
},
ssr: {
// Ambiente SSR com Node.js
build: {
outDir: 'dist/server'
}
},
edge: {
// Ambiente de runtime de edge, como Cloudflare Workers
resolve: {
conditions: ['worker']
},
build: {
outDir: 'dist/edge'
}
}
}
})
Talvez você pense que nunca vai usar isso. É bem provável. A Environment API foi criada principalmente para autores de frameworks: Nuxt, SvelteKit, Astro e outros agora conseguem oferecer suporte a diferentes ambientes de implantação de forma mais elegante.
Para um projeto comum, seja SPA ou MPA, a configuração não muda. O Vite mantém a compatibilidade com versões anteriores, sem exigir qualquer alteração no código.
Então qual é o impacto para você? O impacto indireto é relevante. Quando os frameworks passam a oferecer suporte a mais ambientes, seu projeto ganha mais opções de implantação. O Nuxt pode ser implantado no Cloudflare Workers com uma única ação, e o Astro pode rodar no Deno Deploy. Essas são algumas das possibilidades abertas pela Environment API.
1.2 Suporte ao Node.js e impacto da migração
O Vite 6 oferece suporte oficial ao Node.js 18, 20 e 22 ou superior. O Node.js 21 deixou de ser aceito, pois é uma versão intermediária, fora da linha LTS e pouco usada em produção.
Se o seu projeto ainda usa Node.js 16, chegou a hora de atualizar. A versão mínima aceita da linha Node.js 18 é a 18.18.0, que introduziu alguns recursos usados pelas dependências do Vite.
Pontos que exigem atenção na migração:
- O valor padrão de
resolve.conditionsmudou de['module', 'browser', 'jsnext:main', 'jsnext']para['module', 'browser', 'jsnext:main', 'jsnext', 'import']. Se você configurou essa opção manualmente, talvez precise ajustá-la. - Se você usa um ambiente fora do padrão, como Deno ou Bun, pode ser necessário definir
resolve.conditionsexplicitamente.
Na prática, para a maioria dos projetos, atualizar para o Vite 6 significa apenas trocar a versão. Fiz isso em três projetos, e todos foram resolvidos com uma única linha: npm install vite@latest.
1.3 Outras mudanças importantes
Além da Environment API, o Vite 6 traz outras mudanças que merecem atenção:
A API moderna do Sass passou a ser usada por padrão. Antes, o Vite usava a API legada do Sass; agora, ativa a API moderna por padrão. Se a compilação do Sass apresentar erro, é possível voltar à versão anterior na configuração:
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
api: 'legacy' // Volte à API legada se a API moderna causar problemas
}
}
}
})
Melhorias no stringify de JSON. O Vite agora detecta automaticamente o conteúdo de arquivos JSON. Quando o arquivo inteiro é um objeto estático, ele faz o pré-processamento com JSON.stringify(). Isso reduz o tamanho do bundle, especialmente no caso de arquivos JSON grandes usados como configuração.
Mudanças nas opções de Worker. O valor padrão de worker.format passou de 'iife' para 'es', produzindo Workers no formato ESM. Assim, o sistema de módulos do Worker permanece alinhado ao código principal.
Essas mudanças pouco afetam o desenvolvimento cotidiano. Mas vale prestar atenção ao Sass: em um dos meus projetos, uma função personalizada começou a falhar e levei um bom tempo para descobrir que a causa era a versão da API.
Capítulo 2: integração com o Rolldown e salto de desempenho
2.1 Por que o Vite precisa do Rolldown
Primeiro, um problema incômodo: o Vite 5 usa esbuild no ambiente de desenvolvimento e Rollup em produção. São dois bundlers diferentes.
O que isso significa? O ambiente de desenvolvimento é muito rápido, pois o esbuild foi escrito em Go e compila bem mais rápido do que ferramentas em JavaScript. Mas, na produção, entra o Rollup, um bundler escrito em JavaScript e consideravelmente mais lento.
O sistema de plugins é ainda mais frustrante. A API de plugins do esbuild é completamente diferente da API do Rollup. Um plugin criado para o ambiente de desenvolvimento pode não funcionar em produção, e o contrário também acontece. Essa inconsistência torna a depuração especialmente difícil: tudo parece normal durante o desenvolvimento, mas quebra assim que você executa o build.
O Rolldown foi criado para resolver esse problema.
O que é o Rolldown? Um substituto do Rollup escrito em Rust, compatível com a API de plugins do Rollup, mas de 10 a 30 vezes mais rápido segundo os benchmarks oficiais do Rolldown. Ele também oferece velocidade de compilação comparável à do esbuild.
O plano da equipe do Vite é substituir o Rollup pelo Rolldown e unificar a lógica de empacotamento da produção. Assim, desenvolvimento e produção passam a usar o mesmo sistema de plugins, eliminando muitos dos casos em que algo funciona no desenvolvimento e falha na produção.
2.2 Comparação de desempenho do Rolldown
Os números falam melhor do que promessas. O anúncio do Vite 8 Beta apresentou vários casos:
| Projeto | Mudança no tempo de build | Observação |
|---|---|---|
| Linear | 46s → 6s | Melhora de 87%, citada diretamente no blog oficial |
| Ramp | Redução de 57% | Projeto monorepo de grande porte |
| Mercedes-Benz.io | Redução de 38% | Site empresarial |
| Beehiiv | Redução de 64% | Plataforma de conteúdo |
Todos esses dados foram identificados com sua fonte e vêm do blog oficial do Vite 8 Beta.
O Vite 8 Beta também divulgou os ganhos esperados com o Full Bundle Mode:
- Inicialização do servidor de desenvolvimento 3 vezes mais rápida
- Atualização completa da página 40% mais rápida
- Dez vezes menos requisições de rede
O que é o Full Bundle Mode? Em termos simples, o ambiente de desenvolvimento também passa a usar um bundler, no lugar do modelo anterior em que cada arquivo solicitado era compilado separadamente. A vantagem é acelerar a inicialização e as atualizações; a desvantagem é que a primeira inicialização pode demorar um pouco mais, pois o projeto inteiro precisa ser empacotado.
Esses números parecem surpreendentes. Dez vezes? Trinta vezes? No meu próprio teste, um monorepo com mais de 3.000 arquivos levava 90 segundos para fazer o build com o Vite 5. Depois da troca para o Rolldown, o tempo caiu para 12 segundos, um ganho próximo de 7 vezes. Não chegou a 10 vezes, mas ainda foi uma ótima surpresa.
2.3 Como ativar o Rolldown com rolldown-vite
Hoje há duas formas de usar o Rolldown:
Opção 1: pacote rolldown-vite
Substitua diretamente o pacote vite por rolldown-vite:
// package.json
{
"dependencies": {
"rolldown-vite": "latest"
}
}
Depois, ative-o no vite.config.ts:
export default defineConfig({
build: {
rolldown: true
}
})
Essa opção serve para projetos que querem experimentar a mudança rapidamente. O rolldown-vite troca o Rollup pelo Rolldown de forma automática, e a compatibilidade com plugins costuma ser boa.
Opção 2: esperar pela versão estável do Vite 8
O Vite 8 Beta já integra o Rolldown por padrão. Quando a versão estável for lançada, bastará atualizar:
npm install vite@8
O Vite 8 ainda estava em Beta em dezembro de 2025. Para projetos em produção, é melhor esperar pela versão estável ou começar testando o rolldown-vite em um projeto separado.
Quanto à migração, a recomendação oficial é:
- Testar primeiro com o rolldown-vite e conferir a compatibilidade dos plugins
- Se tudo funcionar, migrar diretamente quando a versão estável do Vite 8 for lançada
- Caso haja algum plugin incompatível, desativar temporariamente o Rolldown e continuar usando o Rollup tradicional
2.4 advancedChunks no lugar de manualChunks
O Rolldown introduz uma nova estratégia de divisão de chunks: advancedChunks. Ela é bem mais flexível do que o manualChunks do Rollup.
Primeiro, veja como o manualChunks do Rollup é configurado:
// manualChunks do Rollup, a forma antiga
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor': ['react', 'react-dom', 'lodash'],
'utils': ['axios', 'dayjs']
}
}
}
}
})
Essa abordagem tem um problema: é preciso definir manualmente a qual chunk cada pacote pertence. Ao adicionar uma dependência nova, se você esquecer de incluí-la, ela pode acabar no bundle principal.
O advancedChunks do Rolldown usa o conceito de grupos:
// advancedChunks do Rolldown, a nova forma
export default defineConfig({
build: {
advancedChunks: {
groups: [
{
name: 'vendor-react',
test: /react|react-dom/,
priority: 10
},
{
name: 'vendor-utils',
test: /lodash|axios|dayjs/,
priority: 5
},
{
name: 'vendor-shared',
test: /[\\/]node_modules[\\/]/,
priority: 1
}
]
}
}
})
Os grupos com prioridade mais alta são verificados primeiro. O que não corresponder a eles segue para o fallback, o último grupo catch-all. A vantagem é não precisar alterar a configuração sempre que uma dependência é adicionada: a expressão regular faz a correspondência automaticamente.
Há ainda um recurso interessante: o advancedChunks consegue detectar dependências duplicadas. Se duas chunks usarem o mesmo pacote, ele extrai esse pacote automaticamente para uma chunk compartilhada. Isso é especialmente útil em monorepos, nos quais vários subprojetos podem usar a mesma biblioteca básica. Antes era necessário cuidar disso manualmente; agora o processo é automático.
Capítulo 3: a evolução do ESM Module Federation
3.1 Solução da comunidade: vite-plugin-federation
Module Federation é um dos principais recursos do Webpack 5. Em projetos grandes com várias equipes, ele permite empacotar diferentes módulos como unidades federadas independentes e usar o código umas das outras. Parece interessante, mas o Vite não oferece suporte nativo.
Como a comunidade resolveu isso? Com o vite-plugin-federation. O plugin tem mais de 3.000 stars no GitHub e hoje é a solução mais madura para Module Federation no Vite.
A configuração é parecida com a do Webpack:
// vite.config.ts - Aplicação Host
import federation from '@originjs/vite-plugin-federation'
export default defineConfig({
plugins: [
federation({
name: 'host-app',
remotes: {
remoteApp: 'http://localhost:5001/assets/remoteEntry.js'
},
shared: ['react', 'react-dom']
})
]
})
// vite.config.ts - Aplicação Remote
import federation from '@originjs/vite-plugin-federation'
export default defineConfig({
plugins: [
federation({
name: 'remote-app',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
'./Header': './src/components/Header'
},
shared: ['react', 'react-dom']
})
]
})
A aplicação Host usa remotes para acessar os módulos da aplicação Remote. A aplicação Remote usa exposes para exportá-los. shared compartilha dependências básicas e evita que elas sejam empacotadas mais de uma vez.
Vantagens dessa solução:
- Compatibilidade com o Webpack Module Federation, permitindo interoperar com projetos Webpack
- Configuração simples, com os mesmos conceitos usados no Webpack
- Comunidade madura e vários casos práticos disponíveis
As desvantagens também são evidentes:
- Não é um recurso nativo do Vite, portanto o plugin pode apresentar problemas de compatibilidade
- No build de produção, usa o Rollup, cuja lógica de empacotamento não é exatamente igual à do Webpack
- A depuração é complexa, principalmente ao localizar erros em referências entre projetos
3.2 Module Federation nativo do Rolldown
A boa notícia é que o Rolldown está implementando suporte nativo a Module Federation.
Já existe um repositório de exemplo chamado rolldown-vite-module-federation-example, que mostra como usar Module Federation com o Rolldown. Porém, a solução ainda está em RC e não é recomendada diretamente para produção.
A solução nativa do Rolldown traz algumas vantagens:
- Compatibilidade completa com a API do Module Federation do Webpack 5
- Lógica de empacotamento unificada, sem alternar entre Vite e Webpack
- Desempenho melhor, pois o próprio Rolldown já é mais rápido do que o Rollup
A configuração ainda está evoluindo e, por enquanto, se parece com isto:
// Rolldown Module Federation, versão RC
export default defineConfig({
build: {
moduleFederation: {
name: 'host-app',
remotes: {
remoteApp: 'remoteApp@http://localhost:5001/remoteEntry.js'
},
exposes: {
'./Component': './src/Component.tsx'
},
shared: {
react: { singleton: true },
reactDom: { singleton: true }
}
}
}
})
A sintaxe é parecida com a do vite-plugin-federation, mas segue mais de perto a especificação do Webpack. singleton: true garante que apenas uma versão seja carregada e evita conflitos entre versões.
3.3 Como escolher uma solução
Qual solução usar para Module Federation hoje?
Projetos em produção: recomendo o vite-plugin-federation.
O motivo é simples: estabilidade. Mais de 3.000 stars indicam que muitas equipes já o utilizam e que boa parte dos problemas conhecidos já foi enfrentada. Quando surge uma dificuldade, também é mais fácil encontrar uma solução na comunidade.
Projetos novos ou experimentais: vale testar a solução nativa do Rolldown.
Se você já usa o Rolldown ou o projeto ainda não foi lançado, pode experimentar. Mas esteja preparado para voltar atrás a qualquer momento, pois a API de uma versão RC ainda pode mudar.
Interoperabilidade com projetos Webpack: as duas soluções funcionam.
O vite-plugin-federation foi projetado para ser compatível com o Webpack. A solução nativa do Rolldown também promete compatibilidade com o Webpack 5.
Ainda assim, Module Federation não resolve tudo. Ele é adequado a projetos grandes com várias equipes e a arquiteturas de micro frontends que exigem implantação independente. Em um projeto comum, pode apenas aumentar a complexidade: é preciso manter mais um limite de federação, coordenar versões de dependências e depurar referências entre projetos.
Se o seu projeto não é tão complexo, não adote Module Federation por impulso. Um monorepo simples ou o compartilhamento por pacotes npm pode ser suficiente.
Capítulo 4: práticas recomendadas de otimização de desempenho
O Vite 6 já é bastante rápido. Mas, se você mantém um projeto grande, com milhares de arquivos e dezenas de dependências, ainda há algumas medidas de otimização disponíveis.
4.1 Aquecer arquivos usados com frequência com warmup
Ao iniciar, o servidor de desenvolvimento do Vite aquece alguns arquivos usados com frequência. Por padrão, ele aquece o arquivo de entrada e suas dependências. É possível indicar outros arquivos manualmente:
export default defineConfig({
server: {
warmup: {
clientFiles: [
'./src/main.tsx',
'./src/pages/Home.tsx',
'./src/pages/Dashboard.tsx'
]
}
}
})
A vantagem do aquecimento é que esses arquivos já terão sido compilados antes de você abrir o navegador. Assim, não há uma espera perceptível no primeiro acesso.
Quais arquivos vale a pena aquecer?
- O arquivo de entrada, que o Vite já trata por padrão
- Componentes de páginas acessadas com frequência
- A entrada de bibliotecas grandes, como
lodash-es
Não aqueça arquivos demais. Uma lista muito grande aumenta o tempo de inicialização. Recomendo limitar a seleção aos 5 a 10 arquivos que você mais usa.
4.2 Evitar Barrel Files
O que são Barrel Files? São arquivos que reexportam uma série de módulos:
// ❌ Barrel File - evite esta abordagem
export { Button } from './Button'
export { Input } from './Input'
export { Modal } from './Modal'
export { Table } from './Table'
O resultado parece organizado: um único import dá acesso a todos os componentes.
import { Button, Input, Modal } from './components'
Mas o Vite lida mal com esse tipo de arquivo. Ele primeiro carrega o barrel file e depois carrega, um por um, os módulos exportados. Isso cria uma cascata de requisições: uma aciona a próxima, que aciona outra.
Em projetos grandes, um barrel file pode exportar dezenas de módulos, e essa cascata pode acrescentar vários segundos ao carregamento.
A forma correta é importar diretamente:
// ✅ Import direto
import Button from './components/Button'
import Input from './components/Input'
O Vite consegue carregar esses módulos independentes em paralelo. Sem a cascata, o ganho de velocidade é perceptível.
Se você realmente quiser manter o código organizado com barrel files, considere o Full Bundle Mode do Rolldown. No modo de empacotamento, a cascata deixa de ser um problema: todos os módulos são reunidos em um único arquivo, sem uma cadeia de requisições.
4.3 Reduzir operações de resolve
Sempre que processa uma instrução import, o Vite executa o resolve para encontrar o caminho real do arquivo. Esse processo envolve verificar node_modules, testar diferentes extensões e tratar aliases de caminho.
Reduzir a quantidade de operações de resolve ajuda a acelerar a compilação.
Informar a extensão do arquivo:
// ❌ Extensão implícita
import Button from './components/Button'
// ✅ Extensão explícita
import Button from './components/Button.tsx'
Com a extensão explícita, o Vite não precisa testar todas as possibilidades, como .ts, .tsx, .js e .jsx.
Reduzir aliases de caminho:
// vite.config.ts
export default defineConfig({
resolve: {
alias: {
'@': '/src',
'@components': '/src/components',
'@utils': '/src/utils',
'@hooks': '/src/hooks',
'@api': '/src/api'
}
}
})
Cada alias aumenta o trabalho do resolve. É melhor manter um ou dois aliases principais, como @, e usar caminhos relativos nos demais casos.
4.4 Plugins nativos e Oxc Transform
O Vite 6 introduziu suporte a plugins nativos. Plugins escritos em Rust são bem mais rápidos do que plugins em JavaScript.
Para ativar:
export default defineConfig({
experimental: {
enableNativePlugin: true
}
})
O recurso ainda é experimental, e a maioria dos plugins ainda não oferece suporte ao modo nativo.
Outro recurso que merece atenção é o Oxc Transform. Oxc é um conjunto de ferramentas de compilação para JavaScript e TypeScript escrito em Rust. A partir da versão 5, o @vitejs/plugin-react usa por padrão o transform do Oxc, que é bem mais rápido do que o Babel.
Se você usa o plugin do React, atualize-o para a versão 5 ou superior:
{
"dependencies": {
"@vitejs/plugin-react": "^5.0.0"
}
}
O transform do Oxc não oferece suporte a todos os recursos do Babel, como plugins personalizados. Se você tiver uma configuração especial do Babel, talvez precise ativá-lo explicitamente no plugin:
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
react({
babel: {
// Força o uso do Babel
plugins: ['your-babel-plugin']
}
})
]
})
Conclusão
Depois de todos esses detalhes, os pontos principais são poucos:
Environment API muda a arquitetura do Vite, mas tem impacto limitado em projetos comuns. Os principais beneficiados são os autores de frameworks, e o ganho indireto para você é ter mais opções de implantação.
Rolldown representa o verdadeiro salto de desempenho. Builds mais de 10 vezes mais rápidos, sistema de plugins unificado e consistência entre desenvolvimento e produção são melhorias concretas. A redução de 46 para 6 segundos no projeto da Linear não é apenas propaganda.
ESM Module Federation ainda está evoluindo. A solução comunitária já é madura e utilizável; a oficial continua em RC. Em cenários de micro frontends, vale começar com o vite-plugin-federation e migrar quando a solução do Rolldown estiver estável.
Otimização de desempenho consiste principalmente em reduzir cascatas, aquecer arquivos usados com frequência e diminuir operações de resolve. O Full Bundle Mode do Rolldown muda várias dessas estratégias, pois o próprio bundler passa a tratar esses problemas no modo de empacotamento.
Recomendações de migração:
- Projetos em produção: teste primeiro a compatibilidade com
rolldown-vitee, se tudo funcionar, espere pela versão estável do Vite 8 para atualizar - Projetos novos: adote diretamente o Vite 8 Beta para aproveitar o desempenho do Rolldown
- Projetos de micro frontends: use
vite-plugin-federatione aguarde a estabilização da solução nativa do Rolldown
O conjunto de ferramentas do Vite está evoluindo rapidamente. A transição da dupla esbuild + Rollup para um Rolldown unificado e o avanço de uma solução de Module Federation compatível com o Webpack para o suporte nativo são mudanças importantes na infraestrutura frontend. Acompanhar esse desenvolvimento e atualizar no momento certo ajuda seu projeto a ficar mais rápido e estável.
FAQ
Qual é o impacto da Environment API do Vite 6 em projetos comuns?
O Rolldown realmente consegue deixar o build 10 vezes mais rápido?
Qual solução escolher hoje para usar Module Federation?
O que exige atenção ao migrar para o Vite 6?
Quais técnicas práticas ajudam a otimizar o desempenho do Vite 6?
Quando vale a pena usar Module Federation?
16 min de leitura · Publicado em: 18 abr 2026 · Atualizado em: 4 set 2026



Comentários
Entre com GitHub para comentar