Programação Por Equipe DevBras

Capa do artigo: Trocar o webpack pelo Vite num projeto Vue sem quebrar o build

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

  1. 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.
  2. Troque as dependências. Remova os pacotes @vue/cli-service e @vue/cli-plugin-*; instale vite e @vitejs/plugin-vue.
  3. Crie o vite.config.js com o plugin do Vue, o alias @ e o proxy que antes estava em devServer.proxy.
  4. Mova o public/index.html para a raiz, remova as expressões <%= BASE_URL %> e acrescente a tag de script que aponta para o ponto de entrada.
  5. Renomeie as variáveis de ambiente de VUE_APP_ para VITE_ e troque process.env por import.meta.env.
  6. Troque require por import e acrescente a extensão nos imports de arquivos .vue.
  7. Atualize os scripts do package.json e rode o build de produção e o preview antes 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_ para VITE_. A variável chega como undefined e a URL da API vira "undefined/pedidos".
  • Deixar process.env no código. No navegador, process não existe e a página quebra com erro de referência.
  • Manter require de imagens. O Vite não processa require no código do navegador e a imagem não carrega.
  • Importar .vue sem 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; vite e @vitejs/plugin-vue instalados.
  • vite.config.js tem alias, proxy e base equivalentes aos antigos.
  • index.html está na raiz e aponta para /src/main.js.
  • Nenhuma ocorrência de process.env ou VUE_APP_ sobrou no código.
  • Imports de componentes têm a extensão .vue.
  • O build e o preview foram 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?

Avalie este artigo

Referência: https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/