Fumadocs + Code Hike
Frontend

Vite

Build tool moderno e rápido para desenvolvimento frontend

O que é Vite?

Vite é um build tool moderno que oferece desenvolvimento extremamente rápido com Hot Module Replacement (HMR) instantâneo e builds otimizados para produção. Criado pelo mesmo autor do Vue.js, mas funciona perfeitamente com React, TypeScript e outras tecnologias.

Por que utilizamos Vite na IngenioLab?

  • Velocidade extrema: Cold start em milissegundos
  • HMR instantâneo: Updates imediatos durante desenvolvimento
  • ESM nativo: Aproveita ES modules nativos do browser
  • TypeScript built-in: Suporte nativo sem configuração
  • Plugin ecosystem: Vasto ecossistema de plugins
  • Build otimizado: Rollup para builds de produção

Instalação e Setup

1. Criar novo projeto:

# React + TypeScript
npm create vite@latest meu-projeto -- --template react-ts
cd meu-projeto
npm install
npm run dev
# Outros templates disponíveis
npm create vite@latest meu-projeto -- --template react
npm create vite@latest meu-projeto -- --template vue-ts
npm create vite@latest meu-projeto -- --template vanilla-ts

2. Estrutura de projeto gerada:

meu-projeto/
├── public/
│ └── vite.svg
├── src/
│ ├── assets/
│ ├── App.tsx
│ ├── App.css
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── index.html # Entry point (não na pasta public!)
├── package.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts # Configuração do Vite

3. Scripts padrão:

{
"scripts": {
"dev": "vite", # Servidor de desenvolvimento
"build": "tsc && vite build", # Build para produção
"preview": "vite preview", # Preview do build
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
}
}

Configuração IngenioLab

1. vite.config.ts básico:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
export default defineConfig({
plugins: [react()],
// Alias para imports limpos
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@/components': path.resolve(__dirname, './src/components'),
'@/hooks': path.resolve(__dirname, './src/hooks'),
'@/services': path.resolve(__dirname, './src/services'),
'@/types': path.resolve(__dirname, './src/types'),
'@/utils': path.resolve(__dirname, './src/utils'),
}
},
// Servidor de desenvolvimento
server: {
port: 3000,
open: true, // Abrir browser automaticamente
host: true, // Permitir acesso externo
cors: true
},
// Build settings
build: {
outDir: 'dist',
sourcemap: true,
// Chunk splitting para melhor caching
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['@tanstack/react-router'],
query: ['@tanstack/react-query']
}
}
}
},
// Variáveis de ambiente
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
},
// Preview settings
preview: {
port: 4173,
open: true
}
})

2. Configuração avançada:

// vite.config.ts - Configuração avançada IngenioLab
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig(({ command, mode }) => {
// Carregar env baseado no mode
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
react({
// Fast Refresh com melhor performance
fastRefresh: true,
// Incluir .js files para Fast Refresh
include: "**/*.{jsx,tsx,js,ts}"
})
],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@/components': resolve(__dirname, 'src/components'),
'@/pages': resolve(__dirname, 'src/pages'),
'@/hooks': resolve(__dirname, 'src/hooks'),
'@/services': resolve(__dirname, 'src/services'),
'@/types': resolve(__dirname, 'src/types'),
'@/utils': resolve(__dirname, 'src/utils'),
'@/assets': resolve(__dirname, 'src/assets'),
'@/styles': resolve(__dirname, 'src/styles'),
}
},
// CSS configuration
css: {
modules: {
localsConvention: 'camelCaseOnly'
},
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
},
server: {
port: Number(env.VITE_PORT) || 3000,
host: env.VITE_HOST || 'localhost',
open: env.VITE_OPEN_BROWSER !== 'false',
// Proxy para API durante desenvolvimento
proxy: {
'/api': {
target: env.VITE_API_URL || 'http://localhost:3001',
changeOrigin: true,
secure: false,
}
},
// Configurações de HMR
hmr: {
overlay: true
}
},
build: {
target: 'esnext',
outDir: 'dist',
assetsDir: 'assets',
sourcemap: mode === 'development',
// Otimizações
minify: 'terser',
terserOptions: {
compress: {
drop_console: mode === 'production',
drop_debugger: true
}
},
rollupOptions: {
output: {
// Chunk strategy
manualChunks: (id) => {
if (id.includes('node_modules')) {
if (id.includes('react')) {
return 'react-vendor'
}
if (id.includes('@tanstack')) {
return 'tanstack-vendor'
}
return 'vendor'
}
},
// Asset naming
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
}
}
},
// Otimizações de dependências
optimizeDeps: {
include: [
'react',
'react-dom',
'@tanstack/react-query',
'@tanstack/react-router'
],
exclude: ['@vite/client', '@vite/env']
},
// Variáveis de ambiente personalizadas
define: {
__APP_VERSION__: JSON.stringify(env.npm_package_version || '1.0.0'),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
__DEV__: command === 'serve'
}
}
})

Plugins Essenciais

1. Plugin React com SWC (mais rápido):

npm install -D @vitejs/plugin-react-swc
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [
react({
// Configurações do SWC
jsxImportSource: '@emotion/react',
plugins: [
// Plugin para styled-components
['@swc/plugin-styled-components', {}]
]
})
]
})

2. PWA Plugin:

npm install -D vite-plugin-pwa
// vite.config.ts
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: 'autoUpdate',
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg}']
},
manifest: {
name: 'IngenioLab App',
short_name: 'IngenioLab',
description: 'Aplicação IngenioLab',
theme_color: '#ffffff',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
}
]
}
})
]
})

3. ESLint Plugin:

npm install -D vite-plugin-eslint
// vite.config.ts
import eslint from 'vite-plugin-eslint'
export default defineConfig({
plugins: [
react(),
eslint({
cache: false,
include: ['./src/**/*.js', './src/**/*.jsx', './src/**/*.ts', './src/**/*.tsx']
})
]
})

Variáveis de Ambiente

1. Configuração de .env:

# .env.development
VITE_APP_TITLE=IngenioLab Dev
VITE_API_URL=http://localhost:3001
VITE_ENABLE_DEVTOOLS=true
# .env.production
VITE_APP_TITLE=IngenioLab
VITE_API_URL=https://api.ingeniolab.com
VITE_ENABLE_DEVTOOLS=false

2. Tipos TypeScript para env:

// src/vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_URL: string
readonly VITE_ENABLE_DEVTOOLS: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

3. Uso nas aplicações:

// src/config/env.ts
export const env = {
appTitle: import.meta.env.VITE_APP_TITLE,
apiUrl: import.meta.env.VITE_API_URL,
enableDevtools: import.meta.env.VITE_ENABLE_DEVTOOLS === 'true',
isDevelopment: import.meta.env.DEV,
isProduction: import.meta.env.PROD
}
// src/services/api.ts
import { env } from '../config/env'
export const apiClient = axios.create({
baseURL: env.apiUrl,
timeout: 10000
})

Asset Handling

1. Importação de assets:

// src/components/Logo.tsx
// Assets estáticos
import logoUrl from '@/assets/logo.png'
import iconUrl from '@/assets/icon.svg?url'
// Inline como base64
import iconInline from '@/assets/small-icon.png?inline'
// Como string (para SVGs)
import iconSvg from '@/assets/icon.svg?raw'
export const Logo = () => {
return (
<div>
<img src={logoUrl} alt="Logo" />
<img src={iconUrl} alt="Icon" />
<img src={iconInline} alt="Inline Icon" />
<div dangerouslySetInnerHTML={{ __html: iconSvg }} />
</div>
)
}

2. Assets dinâmicos:

// src/utils/assets.ts
export const getAssetUrl = (path: string) => {
return new URL(`../assets/${path}`, import.meta.url).href
}
// Uso dinâmico
const imagePath = getAssetUrl(`images/${imageName}.jpg`)

3. Public assets:

<!-- public/index.html -->
<link rel="icon" href="/favicon.ico" />
<!-- src/components/Component.tsx -->
<img src="/images/logo.png" alt="Logo público" />

Performance e Otimizações

1. Code Splitting:

// src/pages/LazyPage.tsx
import { lazy, Suspense } from 'react'
// Lazy loading de componentes
const HeavyComponent = lazy(() => import('@/components/HeavyComponent'))
const Dashboard = lazy(() => import('./Dashboard'))
export const LazyPage = () => (
<div>
<Suspense fallback={<div>Carregando...</div>}>
<HeavyComponent />
</Suspense>
<Suspense fallback={<div>Carregando dashboard...</div>}>
<Dashboard />
</Suspense>
</div>
)

2. Bundle Analysis:

# Instalar bundle analyzer
npm install -D rollup-plugin-visualizer
# Adicionar ao vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
react(),
visualizer({
filename: 'dist/stats.html',
open: true,
gzipSize: true
})
]
})

3. Preloading e Prefetching:

<!-- index.html -->
<head>
<link rel="modulepreload" href="/src/main.tsx" />
<link rel="dns-prefetch" href="https://api.ingeniolab.com" />
</head>

Modo de Desenvolvimento

1. Hot Module Replacement (HMR):

// src/main.tsx
import { createRoot } from 'react-dom/client'
import App from './App'
const container = document.getElementById('root')!
const root = createRoot(container)
root.render(<App />)
// HMR para desenvolvimento
if (import.meta.hot) {
import.meta.hot.accept('./App', () => {
// Re-render quando App.tsx mudar
root.render(<App />)
})
}

2. Configurações de debug:

// vite.config.ts
export default defineConfig({
server: {
hmr: {
overlay: true, // Mostrar erros na tela
clientPort: 3000
}
},
// Source maps detalhados em dev
build: {
sourcemap: process.env.NODE_ENV === 'development' ? 'inline' : false
}
})

Build para Produção

1. Otimizações automáticas:

# Build otimizado
npm run build
# Visualizar resultado
npm run preview

2. Configurações de build:

// vite.config.ts
export default defineConfig({
build: {
// Target moderno para melhor performance
target: 'esnext',
// Minificação
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remover console.logs
drop_debugger: true // Remover debuggers
}
},
// Chunk size limits
rollupOptions: {
output: {
manualChunks: (id) => {
if (id.includes('node_modules')) {
// Separar vendors grandes
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor'
}
return 'vendor'
}
}
}
},
// Asset inline threshold
assetsInlineLimit: 4096, // 4kb
}
})

3. Análise de build:

{
"scripts": {
"build:analyze": "vite build --mode analyze",
"build:report": "npm run build && npx serve dist"
}
}

Integração com TypeScript

1. tsconfig.json otimizado:

{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": [
"src/**/*",
"vite.config.ts"
],
"exclude": [
"node_modules",
"dist"
]
}

Deploy e CI/CD

1. Build para diferentes ambientes:

{
"scripts": {
"build:dev": "vite build --mode development",
"build:staging": "vite build --mode staging",
"build:prod": "vite build --mode production"
}
}

2. Dockerfile otimizado:

# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

3. GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
VITE_API_URL: ${{ secrets.API_URL }}
- name: Deploy
run: echo "Deploy to production"