bookworm-smart-assistant/skills/vue-expert/references/build-tooling.md

481 lines
9.9 KiB
Markdown

# Build Tooling & Vite
---
## Vite Configuration for Vue
### Basic Configuration
```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@components': fileURLToPath(new URL('./src/components', import.meta.url)),
'@composables': fileURLToPath(new URL('./src/composables', import.meta.url)),
'@stores': fileURLToPath(new URL('./src/stores', import.meta.url))
}
}
})
```
### Essential Plugins
```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueDevTools from 'vite-plugin-vue-devtools'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import { QuasarResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
// Vue DevTools integration
VueDevTools(),
// Auto-import components
Components({
dirs: ['src/components'],
resolvers: [QuasarResolver()],
dts: 'src/components.d.ts'
}),
// Auto-import Vue APIs
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: 'src/auto-imports.d.ts',
dirs: ['src/composables'],
vueTemplate: true
})
]
})
```
### Environment Variables
```typescript
// .env
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
// .env.development
VITE_API_URL=http://localhost:3000
// .env.production
VITE_API_URL=https://api.production.com
```
```typescript
// Usage in code
const apiUrl = import.meta.env.VITE_API_URL
const isDev = import.meta.env.DEV
const isProd = import.meta.env.PROD
const mode = import.meta.env.MODE
// Type declarations (env.d.ts)
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_TITLE: string
}
```
```typescript
// vite.config.ts - Define global constants
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
__BUILD_TIME__: JSON.stringify(new Date().toISOString())
}
})
```
### Dev Server Proxy
```typescript
// vite.config.ts
export default defineConfig({
server: {
port: 5173,
host: true,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
'/ws': {
target: 'ws://localhost:3000',
ws: true
}
}
}
})
```
---
## Sourcemaps Configuration
### Development Sourcemaps
```typescript
// vite.config.ts
export default defineConfig({
build: {
// Full sourcemaps for development
sourcemap: true
}
})
```
### Production Sourcemaps
```typescript
// vite.config.ts
export default defineConfig({
build: {
// Options: true | 'inline' | 'hidden' | false
sourcemap: process.env.NODE_ENV === 'production' ? 'hidden' : true
}
})
```
| Mode | Value | Use Case |
|------|-------|----------|
| Full | `true` | Development, staging |
| Hidden | `'hidden'` | Production with error tracking |
| Inline | `'inline'` | Single-file debugging |
| None | `false` | Production without debugging |
### VS Code Debugging
```json
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Debug Vue App",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/src",
"sourceMapPathOverrides": {
"webpack:///./src/*": "${webRoot}/*"
}
}
]
}
```
### Sentry Error Tracking
```typescript
// vite.config.ts
import { sentryVitePlugin } from '@sentry/vite-plugin'
export default defineConfig({
build: {
sourcemap: true
},
plugins: [
sentryVitePlugin({
org: 'your-org',
project: 'your-project',
authToken: process.env.SENTRY_AUTH_TOKEN,
sourcemaps: {
assets: './dist/**',
filesToDeleteAfterUpload: './dist/**/*.map'
}
})
]
})
```
---
## Build Optimization
### Tree Shaking Best Practices
```typescript
// Good: Named imports enable tree shaking
import { ref, computed, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { format, parseISO } from 'date-fns'
// Bad: Namespace imports include everything
import * as Vue from 'vue'
import * as dateFns from 'date-fns'
```
```typescript
// Ensure package.json has sideEffects for proper tree shaking
{
"sideEffects": [
"*.css",
"*.scss",
"*.vue"
]
}
```
### Code Splitting & Lazy Loading
```typescript
// Route-based code splitting
const routes = [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue')
},
{
path: '/settings',
component: () => import('./views/Settings.vue')
}
]
// Component-level lazy loading
const HeavyChart = defineAsyncComponent(() =>
import('./components/HeavyChart.vue')
)
// With loading/error states
const AsyncModal = defineAsyncComponent({
loader: () => import('./components/Modal.vue'),
loadingComponent: LoadingSpinner,
errorComponent: ErrorDisplay,
delay: 200,
timeout: 10000
})
```
### Manual Chunks Configuration
```typescript
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
// Vendor chunk for core dependencies
'vendor': ['vue', 'vue-router', 'pinia'],
// UI framework chunk
'ui': ['quasar', '@quasar/extras'],
// Utility libraries
'utils': ['lodash-es', 'date-fns', 'axios']
}
}
}
}
})
```
```typescript
// Dynamic chunking by package
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
// Split each package into its own chunk
const packageName = id.split('node_modules/')[1].split('/')[0]
return `vendor-${packageName}`
}
}
}
}
}
})
```
### Chunk Size Optimization
```typescript
// vite.config.ts
export default defineConfig({
build: {
// Warn if chunk exceeds 500KB
chunkSizeWarningLimit: 500,
rollupOptions: {
output: {
// Ensure CSS is extracted
assetFileNames: 'assets/[name]-[hash][extname]',
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js'
}
}
}
})
```
### Compression Plugins
```typescript
// vite.config.ts
import viteCompression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
// Gzip compression
viteCompression({
algorithm: 'gzip',
ext: '.gz',
threshold: 1024
}),
// Brotli compression (better ratio)
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
threshold: 1024
})
]
})
```
### Image Optimization
```typescript
// vite.config.ts
import viteImagemin from 'vite-plugin-imagemin'
export default defineConfig({
plugins: [
viteImagemin({
gifsicle: { optimizationLevel: 3 },
optipng: { optimizationLevel: 7 },
mozjpeg: { quality: 80 },
svgo: {
plugins: [
{ name: 'removeViewBox', active: false },
{ name: 'removeEmptyAttrs', active: true }
]
},
webp: { quality: 80 }
})
]
})
```
---
## Performance Analysis
### Bundle Analyzer
```typescript
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
visualizer({
filename: 'stats.html',
open: true,
gzipSize: true,
brotliSize: true,
template: 'treemap' // or 'sunburst', 'network'
})
]
})
```
```bash
# Generate analysis report
npm run build
# Opens stats.html automatically
```
### Build Performance
```typescript
// vite.config.ts
export default defineConfig({
build: {
// Faster builds with esbuild minification
minify: 'esbuild',
// Target modern browsers only
target: 'esnext',
// Disable CSS code splitting for faster builds
cssCodeSplit: false
},
// Optimize dependency pre-bundling
optimizeDeps: {
include: ['vue', 'vue-router', 'pinia', 'axios'],
exclude: ['your-local-package']
}
})
```
### Web Vitals Monitoring
```typescript
// src/utils/vitals.ts
import { onCLS, onFID, onLCP, onFCP, onTTFB } from 'web-vitals'
type VitalMetric = {
name: string
value: number
rating: 'good' | 'needs-improvement' | 'poor'
}
function sendToAnalytics(metric: VitalMetric) {
// Send to your analytics endpoint
console.log(metric)
}
export function initVitals() {
onCLS(sendToAnalytics)
onFID(sendToAnalytics)
onLCP(sendToAnalytics)
onFCP(sendToAnalytics)
onTTFB(sendToAnalytics)
}
```
```typescript
// main.ts
import { initVitals } from './utils/vitals'
if (import.meta.env.PROD) {
initVitals()
}
```
---
## Quick Reference
| Pattern | Use Case |
|---------|----------|
| `@vitejs/plugin-vue` | Vue 3 SFC support |
| `unplugin-vue-components` | Auto-import components |
| `unplugin-auto-import` | Auto-import Vue APIs |
| `manualChunks` | Vendor code splitting |
| `sourcemap: 'hidden'` | Production error tracking |
| `vite-plugin-compression` | Gzip/Brotli compression |
| `rollup-plugin-visualizer` | Bundle size analysis |
| `import.meta.env.VITE_*` | Environment variables |
| `defineAsyncComponent` | Component lazy loading |
| `web-vitals` | Core Web Vitals monitoring |