第 131 章:Vite 进阶配置
学习目标
- 深入理解 Vite 的设计理念与优势
- 掌握 Vite 常用插件与配置
- 学会环境变量、路径别名、HMR 优化
- 在项目中实现按需加载、CDN 注入
一、Vite 是什么
Vite(法语"快")是新一代前端构建工具,基于 ESBuild + Rollup,提供极速的开发体验。
1.1 开发 vs 生产
| 阶段 | 工具 | 特点 |
|---|---|---|
| 开发 | ESBuild | 极速冷启动,按需编译 |
| 生产 | Rollup | 完整打包,Tree-shaking |
1.2 与 Webpack 对比
| 维度 | Vite | Webpack |
|---|---|---|
| 冷启动 | 极快 | 慢 |
| HMR | 极快 | 一般 |
| 配置 | 简洁 | 复杂 |
| 生态 | 增长中 | 成熟 |
| 插件 | Rollup 兼容 | 丰富 |
二、项目初始化
2.1 create-vue
bash
pnpm create vue@latest2.2 手动初始化
bash
pnpm init
pnpm add vue
pnpm add -D vite @vitejs/plugin-vue typescript vue-tsc三、核心配置
3.1 vite.config.ts
typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, '')
}
}
},
build: {
outDir: 'dist',
sourcemap: false,
minify: 'esbuild',
chunkSizeWarningLimit: 1500,
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
'ui-vendor': ['element-plus']
}
}
}
}
});3.2 路径别名
typescript
import path from 'path';
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
}
}
});typescript
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}四、环境变量
4.1 .env 文件
bash
# .env.development
VITE_API_URL=http://localhost:8080
VITE_APP_TITLE=Dev App
# .env.production
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=Production App4.2 在代码中使用
typescript
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.MODE); // 'development' / 'production'
console.log(import.meta.env.DEV); // boolean
console.log(import.meta.env.PROD); // boolean4.3 类型定义
typescript
// src/env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string;
readonly VITE_APP_TITLE: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}4.4 自定义 env 加载
typescript
// vite.config.ts
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), 'VITE_');
return {
define: {
__APP_ENV__: env
}
};
});五、服务器配置
5.1 基础
typescript
server: {
host: '0.0.0.0',
port: 3000,
open: true,
cors: true,
strictPort: false
}5.2 代理
typescript
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
'/socket.io': {
target: 'ws://localhost:8080',
ws: true
}
}
}5.3 HMR 配置
typescript
server: {
hmr: {
protocol: 'ws',
host: 'localhost',
port: 5173,
clientPort: 5173
}
}六、构建优化
6.1 拆分 chunk
typescript
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('vue') || id.includes('pinia')) {
return 'vue-vendor';
}
if (id.includes('element-plus')) {
return 'ui-vendor';
}
return 'vendor';
}
}
}
}
}6.2 压缩
typescript
build: {
minify: 'esbuild', // 默认
// 或 terser
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}6.3 静态资源
typescript
build: {
assetsDir: 'static',
assetsInlineLimit: 4096 // 4KB 以下内联
}6.4 报告分析
bash
pnpm add -D rollup-plugin-visualizertypescript
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
visualizer({ open: true, gzipSize: true, brotliSize: true })
]
});七、常用插件
7.1 Vue 官方
typescript
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()]
});7.2 自动导入
bash
pnpm add -D unplugin-auto-import unplugin-vue-componentstypescript
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
plugins: [
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
resolvers: [ElementPlusResolver()],
dts: 'auto-imports.d.ts'
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'components.d.ts'
})
]
});7.3 SVG 组件
bash
pnpm add -D vite-plugin-svg-iconstypescript
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export default defineConfig({
plugins: [
createSvgIconsPlugin({
iconDirs: [path.resolve(__dirname, 'src/icons')],
symbolId: 'icon-[dir]-[name]'
})
]
});vue
<template>
<svg><use href="#icon-user" /></svg>
</template>7.4 Mock
bash
pnpm add -D vite-plugin-mocktypescript
import { viteMockServe } from 'vite-plugin-mock';
export default defineConfig({
plugins: [
viteMockServe({
mockPath: 'mock',
enable: true
})
]
});typescript
// mock/user.ts
export default [
{
url: '/api/users',
method: 'get',
response: () => ({ data: [{ id: 1, name: 'Tom' }] })
}
];7.5 压缩
bash
pnpm add -D vite-plugin-compressiontypescript
import compression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
compression({
algorithm: 'gzip',
ext: '.gz',
threshold: 10240
})
]
});八、加载优化
8.1 预构建
typescript
optimizeDeps: {
include: ['vue', 'vue-router', 'pinia', 'axios'],
exclude: ['some-large-lib']
}8.2 CDN 注入
typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
vue(),
{
name: 'html-transform',
transformIndexHtml(html) {
if (process.env.NODE_ENV === 'production') {
return html.replace(
'</head>',
`
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
</head>`
);
}
return html;
}
}
],
build: {
rollupOptions: {
external: ['vue'],
output: {
globals: { vue: 'Vue' }
}
}
}
});8.3 动态导入
typescript
// 路由懒加载
const Dashboard = () => import('@/views/Dashboard.vue');
// 条件加载
button.addEventListener('click', async () => {
const { default: Modal } = await import('@/components/Modal.vue');
});九、SSR 配置
typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
build: {
ssr: true,
rollupOptions: {
input: 'src/entry-server.ts'
}
}
});typescript
// src/entry-server.ts
import { createSSRApp } from 'vue';
import App from './App.vue';
export function createApp() {
const app = createSSRApp(App);
return { app };
}十、库模式
typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name: 'MyLib',
fileName: (format) => `my-lib.${format}.js`,
formats: ['es', 'cjs', 'umd']
},
rollupOptions: {
external: ['vue'],
output: {
globals: { vue: 'Vue' }
}
}
}
});json
{
"name": "my-lib",
"files": ["dist"],
"main": "./dist/my-lib.cjs.js",
"module": "./dist/my-lib.es.js",
"types": "./dist/index.d.ts"
}十一、Monorepo 支持
typescript
// vite.config.ts
export default defineConfig({
resolve: {
alias: {
'@my-ui/components': path.resolve(__dirname, '../packages/components/src'),
'@my-ui/utils': path.resolve(__dirname, '../packages/utils/src')
}
},
server: {
fs: {
allow: [path.resolve(__dirname, '..')]
}
}
});十二、CSS 配置
12.1 CSS Modules
typescript
css: {
modules: {
localsConvention: 'camelCase',
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}vue
<style module>
.box {
color: red;
}
</style>
<template>
<div :class="$style.box">...</div>
</template>12.2 预处理器
bash
pnpm add -D sasstypescript
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/variables.scss" as *;`
}
}
}12.3 PostCSS
typescript
css: {
postcss: {
plugins: [
autoprefixer(),
cssnano()
]
}
}十三、调试
13.1 sourcemap
typescript
build: {
sourcemap: true // 或 'hidden'
}13.2 调试 Vite 本身
bash
DEBUG=vite:* pnpm dev13.3 插件 Hook
typescript
const myPlugin = {
name: 'my-plugin',
resolveId(id) {
console.log('[resolveId]', id);
},
load(id) {
console.log('[load]', id);
}
};十四、本章小结
| 概念 | 关键 |
|---|---|
| 路径别名 | alias + tsconfig paths |
| 环境变量 | .env + import.meta.env |
| 代理 | server.proxy |
| 构建 | rollupOptions.output |
| 插件 | unplugin-* 系列 |
| 库模式 | build.lib |
| CSS | modules + preprocessor |
动手练习
- 路径别名:配置
@指向 src 目录 - 环境变量:配置开发/生产环境的 API 地址
- 代理:配置跨域代理转发
- 自动导入:配置 unplugin-auto-import
- 构建优化:拆分 vendor chunk 并分析打包体积
推荐阅读
- 📖 Vite 官方文档 — 权威指南
- 📖 Vite 配置参考 — 所有配置项
- 🌐 awesome-vite — 插件集合
- 📖 Rollup 文档 — 构建底层