DEV Community

Cover image for Migrando uma aplicação Vue 2 legada de Webpack 2 para Vite: Um guia prático baseado em problemas reais
Camila Rody
Camila Rody

Posted on

Migrando uma aplicação Vue 2 legada de Webpack 2 para Vite: Um guia prático baseado em problemas reais

Quando falamos sobre migração para Vite, a maioria dos artigos parte de um cenário ideal: projetos relativamente modernos, dependências atualizadas, versões recentes do Node e uma arquitetura preparada para evoluir. Na prática, porém, muitas empresas ainda mantêm aplicações Vue 2 que surgiram anos atrás, construídas sobre Webpack 2, carregando uma grande quantidade de bibliotecas descontinuadas, loaders obsoletos e configurações que foram sendo adaptadas por diferentes equipes ao longo do tempo.

Foi exatamente esse cenário que encontrei. O objetivo não era migrar para Vue 3, reescrever a aplicação ou modernizar toda a stack de uma vez. O desafio era muito mais delicado: substituir o Webpack 2 por Vite mantendo a aplicação funcionando, preservando compatibilidade com bibliotecas legadas e sem interromper o desenvolvimento do produto.

Ao longo desse processo, ficou evidente que a maior dificuldade não estava na configuração do Vite em si. O verdadeiro desafio era descobrir tudo aquilo que o Webpack estava fazendo silenciosamente há anos e garantir que esse comportamento fosse reproduzido no novo ambiente.

Antes de Instalar o Vite, Entenda o Que o Webpack Faz Pelo Seu Projeto

Um erro bastante comum é iniciar a migração instalando o Vite e tentando fazer a aplicação subir imediatamente. Em aplicações pequenas isso pode funcionar. Em sistemas legados, normalmente gera uma sequência interminável de erros difíceis de rastrear.

Antes de qualquer alteração, é fundamental mapear as responsabilidades atuais do Webpack. Em muitos projetos ele não atua apenas como bundler. Frequentemente também é responsável por resolver aliases, processar imagens, transpilar JavaScript, injetar variáveis de ambiente, tratar arquivos Sass, gerar chunks dinâmicos e fornecer polyfills para APIs que os navegadores não implementam nativamente.

Por isso, o primeiro passo deve ser uma auditoria da configuração existente.

Analise cuidadosamente arquivos como:

webpack.config.js
webpack.dev.js
webpack.prod.js
.babelrc
package.json
Enter fullscreen mode Exit fullscreen mode

Durante essa análise, documente:

  • Aliases utilizados
  • Loaders instalados
  • Plugins do Webpack
  • Configurações do Babel
  • Variáveis de ambiente
  • Polyfills
  • Estratégias de code splitting
  • Tratamento de assets

Essa documentação servirá como roteiro para toda a migração.

Estabilize a Versão do Node Antes de Trocar o Bundler

Em projetos antigos, é comum encontrar versões do Node extremamente defasadas. Muitas vezes o sistema foi desenvolvido utilizando Node 8, Node 10 ou Node 12, e diversas dependências foram escritas considerando limitações dessas versões.

Tentar atualizar Node e substituir Webpack ao mesmo tempo costuma gerar um problema clássico: quando algo quebra, torna-se difícil descobrir a causa.

Por isso, recomendo separar completamente essas etapas.

Primeiro, valide até qual versão do Node a aplicação consegue evoluir sem alterações significativas. Durante essa fase você provavelmente encontrará dependências problemáticas como:

node-sass
extract-text-webpack-plugin
uglify-js
babel-preset-es2015
Enter fullscreen mode Exit fullscreen mode

Em muitos casos, a melhor decisão não é atualizar essas bibliotecas, mas congelá-las temporariamente para reduzir riscos.

O objetivo inicial não é modernizar tudo. É criar um ambiente estável sobre o qual a migração poderá acontecer.

Instale o Vite Sem Remover o Webpack

Uma das decisões mais importantes durante minha migração foi evitar uma substituição imediata.

Em vez de remover o Webpack, o Vite foi introduzido paralelamente.

A instalação básica para Vue 2 é relativamente simples:

npm install vite vite-plugin-vue2 --save-dev
Enter fullscreen mode Exit fullscreen mode

Depois disso, crie um arquivo vite.config.js:

import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'

export default defineConfig({
  plugins: [
    createVuePlugin()
  ]
})
Enter fullscreen mode Exit fullscreen mode

Nesse momento o Webpack continua existindo normalmente.

Os scripts passam a coexistir:

{
  "scripts": {
    "dev": "webpack-dev-server",
    "dev:vite": "vite",
    "build": "webpack",
    "build:vite": "vite build"
  }
}
Enter fullscreen mode Exit fullscreen mode

Essa abordagem permite comparar comportamentos, validar funcionalidades e criar um plano de rollback caso algo inesperado aconteça.

Migrando os Aliases

Quase toda aplicação Vue 2 de médio ou grande porte utiliza aliases para evitar imports relativos extensos.

Um exemplo comum no Webpack:

resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src'),
    '@components': path.resolve(__dirname, 'src/components')
  }
}
Enter fullscreen mode Exit fullscreen mode

Esses aliases precisam ser reproduzidos no Vite.

import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components')
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

Pode parecer um detalhe pequeno, mas em aplicações grandes isso afeta centenas ou milhares de imports.

Por isso, essa costuma ser uma das primeiras configurações que implemento durante a migração.

Corrigindo Imports Dinâmicos Que Funcionavam Apenas no Webpack

Uma das incompatibilidades mais frequentes está relacionada aos famosos require() dinâmicos.

Durante anos o Webpack permitiu padrões como:

const component = require('./pages/' + pageName)
Enter fullscreen mode Exit fullscreen mode

ou

const service = require(path)
Enter fullscreen mode Exit fullscreen mode

O problema é que o Vite utiliza análise estática para resolver módulos e não consegue interpretar caminhos gerados dinamicamente em tempo de execução.

Nesses casos é necessário utilizar import.meta.glob().

Antes:

const component = require(`./pages/${pageName}.vue`)
Enter fullscreen mode Exit fullscreen mode

Depois:

const pages = import.meta.glob('./pages/*.vue')

const component = pages[`./pages/${pageName}.vue`]
Enter fullscreen mode Exit fullscreen mode

Em projetos legados, essa costuma ser uma das etapas mais trabalhosas da migração, pois exige revisão de arquitetura em diversos pontos da aplicação.

Migrando Variáveis de Ambiente

Outro ajuste obrigatório envolve as variáveis de ambiente.

Projetos baseados em Webpack normalmente utilizam:

process.env.API_URL
Enter fullscreen mode Exit fullscreen mode

No Vite o padrão é diferente.

Antes:

const apiUrl = process.env.API_URL
Enter fullscreen mode Exit fullscreen mode

Depois:

const apiUrl = import.meta.env.VITE_API_URL
Enter fullscreen mode Exit fullscreen mode

Além disso, o arquivo .env precisa ser adaptado:

VITE_API_URL=https://api.minhaempresa.com
Enter fullscreen mode Exit fullscreen mode

Um detalhe importante é que o Vite só expõe para o frontend variáveis prefixadas com:

VITE_
Enter fullscreen mode Exit fullscreen mode

Ignorar esse detalhe pode gerar erros difíceis de identificar em ambientes de homologação e produção.

Lidando com Bibliotecas CommonJS e Dependências Abandonadas

Uma das maiores preocupações em sistemas legados é a quantidade de bibliotecas que não acompanham mais a evolução do ecossistema JavaScript.

Muitas delas ainda utilizam:

module.exports = library
Enter fullscreen mode Exit fullscreen mode

ou

exports.default = library
Enter fullscreen mode Exit fullscreen mode

Embora o Vite possua mecanismos de compatibilidade, alguns pacotes exigem otimizações explícitas:

export default defineConfig({
  optimizeDeps: {
    include: [
      'legacy-library',
      'old-plugin'
    ]
  }
})
Enter fullscreen mode Exit fullscreen mode

Quando isso não é suficiente, uma alternativa eficiente é criar wrappers de compatibilidade para isolar o problema e evitar alterações massivas no código.

Essa abordagem reduz significativamente o impacto da migração.

Polyfills: O Problema Que Geralmente Só Aparece Depois

Durante anos o Webpack forneceu diversos polyfills automaticamente.

Quando migramos para Vite, muitos deles desaparecem.

É comum encontrar erros como:

Buffer is not defined
Enter fullscreen mode Exit fullscreen mode
process is not defined
Enter fullscreen mode Exit fullscreen mode
global is not defined
Enter fullscreen mode Exit fullscreen mode

Um exemplo de correção para Buffer:

import { Buffer } from 'buffer'

window.Buffer = Buffer
Enter fullscreen mode Exit fullscreen mode

Esses problemas normalmente surgem apenas durante testes mais profundos, por isso é importante validar cuidadosamente todas as funcionalidades críticas da aplicação.

Revisando Loaders e Assets

Grande parte da complexidade de projetos Webpack antigos está concentrada nos loaders.

É comum encontrar configurações envolvendo:

  • file-loader
  • url-loader
  • raw-loader
  • svg-loader
  • font-loader

A boa notícia é que muitos desses recursos são tratados nativamente pelo Vite.

Entretanto, não assuma que todos os comportamentos serão reproduzidos automaticamente.

Sempre valide:

  • SVGs inline
  • Fontes customizadas
  • Arquivos estáticos
  • Assets importados dinamicamente
  • Recursos utilizados por bibliotecas de terceiros

Muitos bugs de produção surgem exatamente nessa etapa.

Validando a Build de Produção

Fazer a aplicação funcionar em desenvolvimento não significa que a migração terminou.

Na verdade, a parte mais importante começa depois.

Uma validação completa deve incluir:

  • Navegação entre rotas
  • Lazy loading
  • Autenticação
  • Upload de arquivos
  • Integrações externas
  • Variáveis de ambiente
  • Source maps
  • Geração de bundles

Além disso, recomendo comparar o comportamento da aplicação construída pelo Webpack e pelo Vite simultaneamente durante algum tempo.

Essa estratégia facilita a identificação de regressões e reduz significativamente os riscos da implantação.

Conclusão

Depois de concluir essa migração, uma percepção ficou muito clara para mim: trocar Webpack por Vite é a parte fácil.

O trabalho real está em compreender todas as decisões arquiteturais acumuladas ao longo dos anos e identificar quais delas dependem diretamente do comportamento do Webpack.

Aliases, imports dinâmicos, polyfills, bibliotecas CommonJS, loaders antigos e configurações herdadas raramente aparecem na documentação do projeto. Muitas vezes, só descobrimos sua importância quando algo deixa de funcionar.

Por isso, a melhor estratégia não é migrar rápido. É migrar de forma controlada, mantendo Webpack e Vite coexistindo durante o processo, validando cada etapa e reduzindo ao máximo a quantidade de variáveis envolvidas.

Em aplicações Vue 2 legadas, o sucesso da migração não está em instalar uma ferramenta nova. Está em conseguir modernizar a infraestrutura sem alterar o comportamento que o sistema construiu ao longo dos anos.

Top comments (0)