696 lines
13 KiB
Markdown
696 lines
13 KiB
Markdown
---
|
|
tags: [DEV, VITE, configuration, typescript]
|
|
create time: 2026-04-18
|
|
---
|
|
|
|
# Vite 配置详解
|
|
|
|
## 配置文件结构
|
|
|
|
Vite 配置文件支持多种格式:`vite.config.js`、`vite.config.ts`,推荐使用 TypeScript 获得类型提示。
|
|
|
|
完整配置结构示例:
|
|
|
|
```typescript
|
|
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import path from 'path'
|
|
|
|
export default defineConfig({
|
|
// 插件配置
|
|
plugins: [react()],
|
|
|
|
// 路径别名
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src'),
|
|
'@components': path.resolve(__dirname, './src/components'),
|
|
'@hooks': path.resolve(__dirname, './src/hooks')
|
|
}
|
|
},
|
|
|
|
// 开发服务器配置
|
|
server: {
|
|
port: 3000,
|
|
host: true,
|
|
open: true,
|
|
cors: true
|
|
},
|
|
|
|
// 构建配置
|
|
build: {
|
|
outDir: 'dist',
|
|
sourcemap: true
|
|
}
|
|
})
|
|
```
|
|
|
|
## 核心配置项
|
|
|
|
### resolve 模块解析
|
|
|
|
#### 路径别名
|
|
```typescript
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src'),
|
|
// 支持目录别名
|
|
'@components': path.resolve(__dirname, './src/components'),
|
|
'@utils': path.resolve(__dirname, './src/utils')
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 扩展名解析
|
|
```typescript
|
|
resolve: {
|
|
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
|
|
}
|
|
```
|
|
|
|
### server 开发服务器
|
|
|
|
```typescript
|
|
server: {
|
|
// 端口配置
|
|
port: 3000,
|
|
strictPort: false, // 端口被占用时自动尝试下一个
|
|
host: true, // 监听所有网络地址
|
|
|
|
// 自动打开浏览器
|
|
open: true,
|
|
openPage: '/dashboard',
|
|
|
|
// CORS 配置
|
|
cors: true,
|
|
|
|
// 代理配置
|
|
proxy: {
|
|
'/api': {
|
|
target: 'http://localhost:8080',
|
|
changeOrigin: true,
|
|
rewrite: (path) => path.replace(/^\/api/, '')
|
|
},
|
|
'/assets': {
|
|
target: 'http://localhost:9000',
|
|
changeOrigin: true
|
|
}
|
|
},
|
|
|
|
// HMR 配置
|
|
hmr: {
|
|
overlay: true, // 显示错误覆盖层
|
|
port: 24678 // HMR WebSocket 端口
|
|
},
|
|
|
|
// 中间件模式 (用于 SSR)
|
|
middlewareMode: false
|
|
}
|
|
```
|
|
|
|
### load 环境变量
|
|
|
|
```bash
|
|
# .env.development
|
|
VITE_API_URL=http://localhost:8080/api
|
|
VITE_APP_NAME=Dev Environment
|
|
|
|
# .env.production
|
|
VITE_API_URL=https://api.example.com
|
|
VITE_APP_NAME=Production
|
|
```
|
|
|
|
```typescript
|
|
// 类型定义
|
|
interface ImportMetaEnv {
|
|
readonly VITE_API_URL: string
|
|
readonly VITE_APP_NAME: string
|
|
}
|
|
|
|
// 使用环境变量
|
|
const apiUrl = import.meta.env.VITE_API_URL
|
|
const appName = import.meta.env.VITE_APP_NAME
|
|
|
|
// 自定义环境变量访问
|
|
export default defineConfig(({ mode }) => {
|
|
return {
|
|
define: {
|
|
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
|
|
__ENV__: JSON.stringify(mode)
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
### build 构建配置
|
|
|
|
```typescript
|
|
build: {
|
|
// 输出目录
|
|
outDir: 'dist',
|
|
assetsDir: 'assets',
|
|
|
|
// Source Map 配置
|
|
sourcemap: false, // 生产环境关闭
|
|
sourcemapExcludeSources: false,
|
|
|
|
// 压缩配置
|
|
minify: 'terser', // terser | esbuild
|
|
terserOptions: {
|
|
compress: {
|
|
drop_console: true, // 移除 console
|
|
drop_debugger: true, // 移除 debugger
|
|
pure_funcs: ['console.log', 'console.info']
|
|
}
|
|
},
|
|
|
|
// 代码分割配置
|
|
rollupOptions: {
|
|
output: {
|
|
// 手动代码分割
|
|
manualChunks: {
|
|
'vendor-react': ['react', 'react-dom'],
|
|
'vendor-ui': ['antd', '@ant-design/icons'],
|
|
'vendor-utils': ['lodash', 'dayjs']
|
|
},
|
|
// 文件名模式
|
|
chunkFileNames: 'js/[name]-[hash].js',
|
|
entryFileNames: 'js/[name]-[hash].js',
|
|
assetFileNames: '[ext]/[name]-[hash].[ext]'
|
|
}
|
|
},
|
|
|
|
// 构建优化
|
|
chunkSizeWarningLimit: 1000, // 警告限制
|
|
rollupOptions: {
|
|
output: {
|
|
// 内联动态导入
|
|
inlineDynamicImports: false,
|
|
// 保留模块结构
|
|
preserveModules: false
|
|
}
|
|
},
|
|
cssCodeSplit: true,
|
|
reportCompressedSize: false,
|
|
target: 'es2015'
|
|
}
|
|
```
|
|
|
|
### preview 预览配置
|
|
|
|
```typescript
|
|
preview: {
|
|
port: 4173,
|
|
strictPort: false,
|
|
host: true,
|
|
open: true,
|
|
|
|
// 预览服务器配置
|
|
cors: true,
|
|
|
|
// 中间件
|
|
middlewares: [
|
|
// 自定义中间件
|
|
]
|
|
}
|
|
```
|
|
|
|
## CSS 配置
|
|
|
|
### CSS Modules
|
|
```typescript
|
|
css: {
|
|
modules: {
|
|
// 命名规范
|
|
localsConvention: 'camelCase', // camelCase | camelCaseOnly | dashes | dashesOnly
|
|
|
|
// 作用域行为
|
|
scopeBehaviour: 'local', // local | global
|
|
|
|
// 类名生成
|
|
generateScopedName: '[name]__[local]___[hash:base64:5]',
|
|
|
|
// Hash 生成函数
|
|
hashPrefix: 'prefix',
|
|
|
|
// 全局模块路径
|
|
globalModulePaths: [/node_modules/]
|
|
}
|
|
}
|
|
```
|
|
|
|
### CSS 预处理器
|
|
```typescript
|
|
css: {
|
|
preprocessorOptions: {
|
|
scss: {
|
|
additionalData: `@import "@/styles/variables.scss";`,
|
|
api: 'modern-compiler' // 使用现代编译器
|
|
},
|
|
less: {
|
|
modifyVars: {
|
|
'primary-color': '#1890ff'
|
|
},
|
|
javascriptEnabled: true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### PostCSS 配置
|
|
```javascript
|
|
// postcss.config.js
|
|
export default {
|
|
plugins: {
|
|
autoprefixer: {},
|
|
'cssnano': {
|
|
preset: 'default'
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 插件系统
|
|
|
|
### 插件配置流程
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[vite.config.ts] --> B[插件导入]
|
|
B --> C[插件配置]
|
|
C --> D[插件注册]
|
|
D --> E[构建流程]
|
|
E --> F[插件执行]
|
|
```
|
|
|
|
### 官方插件
|
|
|
|
#### React 插件
|
|
```typescript
|
|
import react from '@vitejs/plugin-react'
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
react({
|
|
// Babel 转换
|
|
babel: {
|
|
plugins: ['emotion']
|
|
},
|
|
// JSX 运行时
|
|
jsxRuntime: 'automatic', // classic | automatic
|
|
// 开发工具
|
|
devtools: true,
|
|
// 包含
|
|
include: /\.(jsx|js|tsx|ts)$/,
|
|
// 排除
|
|
exclude: /\.node_modules/
|
|
})
|
|
]
|
|
})
|
|
```
|
|
|
|
#### Vue 插件
|
|
```typescript
|
|
import vue from '@vitejs/plugin-vue'
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
vue({
|
|
// Vue 编译器选项
|
|
template: {
|
|
compilerOptions: {
|
|
isCustomElement: (tag) => tag.includes('-'),
|
|
whitespace: 'condense'
|
|
}
|
|
},
|
|
// 脚本配置
|
|
script: {
|
|
defineModel: true,
|
|
propsDestructure: true
|
|
},
|
|
// 样式配置
|
|
style: {
|
|
scoped: true
|
|
}
|
|
})
|
|
]
|
|
})
|
|
```
|
|
|
|
### 自定义插件
|
|
|
|
#### 基础插件结构
|
|
```typescript
|
|
import type { Plugin } from 'vite'
|
|
|
|
export function myCustomPlugin(): Plugin {
|
|
return {
|
|
name: 'my-custom-plugin',
|
|
|
|
// 配置阶段
|
|
config(config) {
|
|
return {
|
|
// 返回配置修改
|
|
}
|
|
},
|
|
|
|
configResolved(config) {
|
|
// 配置已解析
|
|
console.log('Vite config resolved:', config)
|
|
},
|
|
|
|
// 配置开发服务器
|
|
configureServer(server) {
|
|
// 自定义服务器中间件
|
|
server.middlewares.use((req, res, next) => {
|
|
if (req.url === '/custom-endpoint') {
|
|
res.statusCode = 200
|
|
res.setHeader('Content-Type', 'application/json')
|
|
res.end(JSON.stringify({ message: 'Custom response' }))
|
|
} else {
|
|
next()
|
|
}
|
|
})
|
|
|
|
// 返回清理函数
|
|
return () => {
|
|
console.log('Server closed')
|
|
}
|
|
},
|
|
|
|
// 转换钩子
|
|
transform(code, id) {
|
|
// 转换代码
|
|
if (id.endsWith('.custom')) {
|
|
return {
|
|
code: convertCustomFormat(code),
|
|
map: null
|
|
}
|
|
}
|
|
},
|
|
|
|
// 模块解析钩子
|
|
resolveId(source) {
|
|
// 自定义模块解析
|
|
if (source === 'virtual-module') {
|
|
return '\0virtual-module'
|
|
}
|
|
},
|
|
|
|
// 加载钩子
|
|
load(id) {
|
|
// 加载模块内容
|
|
if (id === '\0virtual-module') {
|
|
return 'export const msg = "Hello from virtual module"'
|
|
}
|
|
},
|
|
|
|
// 构建钩子
|
|
buildStart() {
|
|
console.log('Build started')
|
|
},
|
|
|
|
buildEnd() {
|
|
console.log('Build completed')
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 环境变量插件
|
|
```typescript
|
|
import type { Plugin } from 'vite'
|
|
|
|
export function envPlugin(): Plugin {
|
|
return {
|
|
name: 'env-plugin',
|
|
config(config, { mode }) {
|
|
// 加载环境变量
|
|
const env = loadEnv(mode, process.cwd(), '')
|
|
|
|
return {
|
|
define: {
|
|
'import.meta.env': JSON.stringify(env)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 第三方插件推荐
|
|
|
|
#### 路径别名插件
|
|
```typescript
|
|
import { viteCommonjs } from '@originjs/vite-plugin-commonjs'
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
react(),
|
|
viteCommonjs() // 支持 CommonJS 模块
|
|
]
|
|
})
|
|
```
|
|
|
|
#### 压缩插件
|
|
```typescript
|
|
import viteCompression from 'vite-plugin-compression'
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
viteCompression({
|
|
verbose: true,
|
|
disable: false,
|
|
threshold: 10240,
|
|
algorithm: 'gzip',
|
|
ext: '.gz'
|
|
})
|
|
]
|
|
})
|
|
```
|
|
|
|
#### 组件按需加载
|
|
```typescript
|
|
import Components from 'unplugin-vue-components/vite'
|
|
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
Components({
|
|
resolvers: [
|
|
AntDesignVueResolver()
|
|
]
|
|
})
|
|
]
|
|
})
|
|
```
|
|
|
|
## TypeScript 配置
|
|
|
|
### tsconfig.json
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"target": "ES2020",
|
|
"useDefineForClassFields": true,
|
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
"module": "ESNext",
|
|
"skipLibCheck": true,
|
|
"moduleResolution": "bundler",
|
|
"allowImportingTsExtensions": true,
|
|
"resolveJsonModule": true,
|
|
"isolatedModules": true,
|
|
"noEmit": true,
|
|
"jsx": "react-jsx",
|
|
"strict": true,
|
|
"noUnusedLocals": true,
|
|
"noUnusedParameters": true,
|
|
"noFallthroughCasesInSwitch": true,
|
|
"baseUrl": ".",
|
|
"paths": {
|
|
"@/*": ["src/*"]
|
|
}
|
|
},
|
|
"include": ["src", "vite.config.ts"],
|
|
"references": [{ "path": "./tsconfig.node.json" }]
|
|
}
|
|
```
|
|
|
|
### tsconfig.node.json (为 Vite 配置文件提供类型)
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"composite": true,
|
|
"skipLibCheck": true,
|
|
"module": "ESNext",
|
|
"moduleResolution": "bundler",
|
|
"allowSyntheticDefaultImports": true,
|
|
"strict": true
|
|
},
|
|
"include": ["vite.config.ts"]
|
|
}
|
|
```
|
|
|
|
## 高级配置
|
|
|
|
### 多入口配置
|
|
```typescript
|
|
import { defineConfig } from 'vite'
|
|
import path from 'path'
|
|
|
|
export default defineConfig({
|
|
build: {
|
|
rollupOptions: {
|
|
input: {
|
|
main: path.resolve(__dirname, 'index.html'),
|
|
admin: path.resolve(__dirname, 'admin.html'),
|
|
landing: path.resolve(__dirname, 'landing.html')
|
|
}
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
### 库模式配置
|
|
```typescript
|
|
export default defineConfig({
|
|
build: {
|
|
lib: {
|
|
entry: path.resolve(__dirname, 'src/index.ts'),
|
|
name: 'MyLibrary',
|
|
fileName: (format) => `my-library.${format}.js`,
|
|
formats: ['es', 'umd']
|
|
},
|
|
rollupOptions: {
|
|
external: ['react', 'react-dom'],
|
|
output: {
|
|
globals: {
|
|
react: 'React',
|
|
'react-dom': 'ReactDOM'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
### SSR 配置
|
|
```typescript
|
|
export default defineConfig({
|
|
build: {
|
|
ssr: true, // 启用 SSR
|
|
outDir: 'dist/server', // SSR 输出目录
|
|
rollupOptions: {
|
|
input: './src/entry-server.ts'
|
|
}
|
|
},
|
|
server: {
|
|
middlewareMode: 'ssr' // SSR 模式
|
|
}
|
|
})
|
|
```
|
|
|
|
## 配置最佳实践
|
|
|
|
### 环境分离
|
|
```typescript
|
|
// vite.config.ts
|
|
export default defineConfig(({ mode }) => {
|
|
return {
|
|
plugins: [
|
|
mode === 'development' ? devPlugin() : prodPlugin()
|
|
],
|
|
server: mode === 'development' ? devServerConfig : {}
|
|
}
|
|
})
|
|
```
|
|
|
|
### 配置复用
|
|
```typescript
|
|
// shared-config.ts
|
|
export const baseConfig = {
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src')
|
|
}
|
|
}
|
|
}
|
|
|
|
export const devConfig = {
|
|
...baseConfig,
|
|
server: {
|
|
port: 3000
|
|
}
|
|
}
|
|
|
|
export const buildConfig = {
|
|
...baseConfig,
|
|
build: {
|
|
outDir: 'dist'
|
|
}
|
|
}
|
|
```
|
|
|
|
### 配置验证
|
|
```typescript
|
|
function validateConfig(config: UserConfig) {
|
|
if (!config.plugins) {
|
|
throw new Error('Plugins are required')
|
|
}
|
|
|
|
// 验证路径别名
|
|
if (config.resolve?.alias) {
|
|
Object.entries(config.resolve.alias).forEach(([key, value]) => {
|
|
if (!path.isAbsolute(value)) {
|
|
throw new Error(`Alias ${key} must be an absolute path`)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
```
|
|
|
|
## 故障排查
|
|
|
|
### 配置加载问题
|
|
```bash
|
|
# 调试配置加载
|
|
DEBUG=vite:config npm run dev
|
|
|
|
# 检查配置语法
|
|
node -c vite.config.ts
|
|
```
|
|
|
|
### 路径解析问题
|
|
```typescript
|
|
// 使用 debug 插件检查路径
|
|
import { defineConfig } from 'vite'
|
|
|
|
export default defineConfig({
|
|
resolve: {
|
|
alias: {
|
|
'debug': require.resolve('debug')
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
### 插件冲突诊断
|
|
```typescript
|
|
// 在插件开发中添加日志
|
|
export function debugPlugin() {
|
|
return {
|
|
name: 'debug-plugin',
|
|
transform(code, id) {
|
|
console.log('Transforming:', id)
|
|
return null
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
配置是 Vite 项目的核心,合理的配置能显著提升开发体验和构建质量。根据项目规模和需求,逐步完善配置是最佳实践。
|
|
|
|
相关文档:
|
|
- [[DEV/VITE/架构原理.md]] - 理解配置的底层机制
|
|
- [[DEV/VITE/优化实践.md]] - 配置优化技巧
|