Trocar o webpack pelo Vite num projeto Vue sem quebrar o build
Comece um projeto Vue novo no Vite ou migre um projeto do Vue CLI: vite.config.js, index.html na raiz, variáveis VITE_, imports com .vue e o teste do build de produção.
No painel de rastreio de uma transportadora, feito com Vue 3 e Vue CLI, a equipe espera perto de um minuto para o servidor de desenvolvimento subir e alguns segundos a cada vez que salva um arquivo. O vue.config.js tem regras de loader que ninguém lembra por que existem. A resposta curta: projeto Vue novo começa no Vite (é o que o npm create vue@latest gera hoje), e projeto existente no Vue CLI pode migrar em uma tarde, desde que você troque cinco coisas: a configuração, o lugar do index.html, o prefixo das variáveis de ambiente, os require e os imports sem extensão .vue. Fique no webpack só se o projeto depende de algo que só existe nele.
O Vue CLI está em modo de manutenção, e a documentação oficial do Vue recomenda o Vite para projetos novos. Isso não obriga ninguém a migrar amanhã, mas significa que o tempo joga contra quem fica.
Por que o Vite é mais rápido no desenvolvimento
O webpack, no modo de desenvolvimento, monta um pacote com o aplicativo inteiro antes de servir a primeira página. Quanto maior o projeto, maior a espera para subir e para reconstruir depois de cada alteração.
O Vite parte de outro princípio: os navegadores atuais carregam módulos JavaScript nativos. O servidor de desenvolvimento entrega cada arquivo quando o navegador pede, transformando só aquele arquivo (um .vue vira JavaScript, um .scss vira CSS). Ao salvar, só o módulo alterado é trocado na página. As dependências de node_modules são pré-processadas uma vez e ficam em cache.
Para produção, a história é diferente. O Vite gera um pacote otimizado, com divisão de código e hash no nome dos arquivos, pronto para cache longo. Ou seja: em desenvolvimento ele não empacota; em produção, empacota. Essa diferença explica o cuidado mais importante deste guia, que é testar o build de produção antes de comemorar.
Como começar um projeto novo
npm create vue@latest painel-rastreio
cd painel-rastreio
npm install
npm run dev
O assistente pergunta se você quer TypeScript, Vue Router, Pinia, testes e lint. O projeto gerado já vem com vite.config.js, alias @ apontando para src e os scripts dev, build e preview.
Como migrar um projeto do Vue CLI
- Crie uma branch e anote os tempos atuais. Quanto leva para subir o servidor e quanto leva uma alteração para aparecer na tela. Sem esse número, você não sabe se a migração valeu.
- Troque as dependências. Remova os pacotes
@vue/cli-servicee@vue/cli-plugin-*; instalevitee@vitejs/plugin-vue. - Crie o
vite.config.jscom o plugin do Vue, o alias@e o proxy que antes estava emdevServer.proxy. - Mova o
public/index.htmlpara a raiz, remova as expressões<%= BASE_URL %>e acrescente a tag de script que aponta para o ponto de entrada. - Renomeie as variáveis de ambiente de
VUE_APP_paraVITE_e troqueprocess.envporimport.meta.env. - Troque
requireporimporte acrescente a extensão nos imports de arquivos.vue. - Atualize os scripts do
package.jsone rode o build de produção e opreviewantes de abrir o pull request.
O vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 8080,
proxy: {
'/api': 'http://localhost:5000'
}
}
})
Se o app era publicado numa subpasta, o antigo publicPath vira a opção base, por exemplo base: '/painel/'. A pasta de saída continua sendo dist por padrão.
O index.html na raiz
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>Painel de rastreio</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
No Vite, o index.html é o ponto de entrada de verdade. Ele não é um modelo onde o empacotador injeta scripts; é ele que aponta para o main.js. A pasta public continua existindo para arquivos copiados sem processamento, como o favicon.
Variáveis de ambiente, require e extensões
Uma linha típica do painel antes e depois:
// antes (Vue CLI)
const apiUrl = process.env.VUE_APP_API_URL
const logo = require('@/assets/logo.png')
import MapaEntregas from '@/components/MapaEntregas'
// depois (Vite)
import logo from '@/assets/logo.png'
import MapaEntregas from '@/components/MapaEntregas.vue'
const apiUrl = import.meta.env.VITE_API_URL
O Vite só expõe ao código do navegador as variáveis com prefixo VITE_, o que é uma proteção: uma senha de banco no .env não vai parar no JavaScript público por engano. Lembre que tudo com esse prefixo fica visível para qualquer pessoa que abra o DevTools; segredo de verdade não pertence ao front.
A extensão importa porque a lista padrão de extensões resolvidas automaticamente pelo Vite não inclui .vue. O import sem extensão falha com "failed to resolve import". Dá para configurar a lista, mas escrever a extensão é mais explícito e evita surpresa.
Os scripts do package.json
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
Se o projeto usa Sass, instale o pacote sass como dependência de desenvolvimento; o Vite processa .scss sem loader configurado. Projetos ainda em Vue 2 precisam primeiro chegar à versão 2.7 para usar o plugin @vitejs/plugin-vue2. Como o Vue 2 não recebe mais atualizações desde o fim de 2023, essa é uma boa hora para planejar a ida ao Vue 3.
O que testar antes de publicar
O modo de desenvolvimento é mais tolerante do que o build. Um import circular, um arquivo com letra maiúscula diferente no nome (que funciona no Windows e falha no Linux do servidor) ou uma variável de ambiente esquecida podem passar no npm run dev e quebrar no npm run build. Rode o build, depois o npm run preview, e navegue pelas telas principais como se fosse a pessoa usuária.
No painel da transportadora, os números da equipe ficaram assim: o servidor de desenvolvimento passou de 52 segundos para pouco mais de 1 segundo para subir, e a atualização após salvar ficou praticamente instantânea. O build de produção ficou um pouco mais rápido, mas não foi esse o ganho que mudou o dia a dia. Seu resultado vai variar; por isso a primeira etapa é medir.
Quando ficar no webpack
Migrar por moda quebra mais do que ajuda. Fique onde está se o projeto usa Module Federation para carregar partes de outros apps em tempo de execução, se depende de um loader ou plugin próprio sem equivalente, ou se o build está embutido num pipeline que só entende a saída atual. Nesses casos, avalie o custo de reescrever essa peça antes de mexer no resto. A arquitetura do app (rotas, estado, chamadas de API) não muda com a troca; o que muda é o ciclo de edição.
Erros comuns
- Esquecer de renomear
VUE_APP_paraVITE_. A variável chega comoundefinede a URL da API vira "undefined/pedidos". - Deixar
process.envno código. No navegador,processnão existe e a página quebra com erro de referência. - Manter
requirede imagens. O Vite não processarequireno código do navegador e a imagem não carrega. - Importar
.vuesem extensão. O servidor recusa o import e a tela fica em branco. - Testar só com
npm run dev. Erros que só aparecem no build vão direto para produção. - Colocar segredo em variável
VITE_. Ele vai para o JavaScript público e qualquer pessoa lê.
Checklist
- Os tempos de subida e de atualização foram medidos antes e depois.
- Pacotes do Vue CLI removidos;
vitee@vitejs/plugin-vueinstalados. vite.config.jstem alias, proxy ebaseequivalentes aos antigos.index.htmlestá na raiz e aponta para/src/main.js.- Nenhuma ocorrência de
process.envouVUE_APP_sobrou no código. - Imports de componentes têm a extensão
.vue. - O build e o
previewforam testados nas telas principais.
Rode o servidor de desenvolvimento do seu projeto Vue com um cronômetro na mão. Quantos segundos a equipe perde nisso por dia, somando todo mundo?
Referência: https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/