配置文件
配置文件基础
Vite 会自动解析项目根目录下的配置文件。支持的配置文件名:
vite.config.jsvite.config.mjsvite.config.tsvite.config.cjs
推荐使用 vite.config.js 或 vite.config.ts(TypeScript 项目)。
配置加载方式
默认情况下,Vite 使用 Rolldown 将配置文件打包到临时文件中加载。这种方式的优点是可以支持 TypeScript 和 ESM 语法,但在 monorepo 中导入 TypeScript 文件时可能会遇到问题。
Vite 提供三种配置加载方式,可通过 --configLoader 选项指定:
bundle 模式(默认)
vite --configLoader bundle
使用 Rolldown 将配置文件打包到 node_modules/.vite-temp 目录后加载。特点:
- 完整支持 TypeScript 和 ESM
- 支持
package.json中的"type": "module"配置 - 在 monorepo 中可能遇到模块解析问题
runner 模式
vite --configLoader runner
使用模块运行器即时转换文件,不创建临时配置文件。特点:
- 不创建临时文件,避免 monorepo 中的路径问题
- 不支持配置文件中的 CommonJS 语法
- 外部 CJS 包可以正常工作
native 模式
vite --configLoader native
使用环境的原生运行时加载配置文件。特点:
- 适用于支持 TypeScript 的环境(如
node --experimental-strip-types) - 或仅编写纯 JavaScript 的情况
- 配置文件导入的模块更新不会被检测到,Vite 服务器不会自动重启
注意:使用 VS Code 调试配置文件时,如果使用默认的 bundle 模式,需要在 .vscode/settings.json 中添加配置:
{
"debug.javascript.terminalOptions": {
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**",
"**/node_modules/.vite-temp/**"
]
}
}
基本配置结构
import { defineConfig } from 'vite'
export default defineConfig({
// 配置选项
})
defineConfig 辅助函数提供类型提示,无需 JSDoc 注解即可获得 IDE 智能提示。
使用 JSDoc 类型提示
如果不使用 defineConfig,也可以用 JSDoc 注解:
/** @type {import('vite').UserConfig} */
export default {
// 配置选项
}
TypeScript 配置文件
对于 TypeScript 项目,可以使用 vite.config.ts:
import { defineConfig } from 'vite'
import type { UserConfig } from 'vite'
export default defineConfig({
// 配置选项
} satisfies UserConfig)
条件配置
如果配置需要根据命令(serve 或 build)、模式或其他条件动态确定,可以导出一个函数:
import { defineConfig } from 'vite'
export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
if (command === 'serve') {
return {
// 开发环境特定配置
server: {
port: 3000,
},
}
} else {
// command === 'build'
return {
// 生产环境特定配置
build: {
rollupOptions: {
// 生产构建选项
},
},
}
}
})
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
command | 'build' | 'serve' | 当前运行的命令(serve 表示开发服务器,build 表示生产构建) |
mode | string | 应用运行的模式 |
isSsrBuild | boolean | undefined | 是否为 SSR 构建 |
isPreview | boolean | undefined | 是否为预览模式 |
异步配置
如果配置需要调用异步函数,可以导出异步函数:
import { defineConfig } from 'vite'
export default defineConfig(async ({ command, mode }) => {
const data = await asyncFunction()
return {
// 使用异步获取的数据
define: {
__APP_DATA__: JSON.stringify(data),
},
}
})
常用配置选项
项目根目录
export default defineConfig({
// 项目根目录(index.html 所在位置)
// 默认:process.cwd()
root: process.cwd(),
// 基础公共路径
// 默认:'/'
base: '/',
// 资源公共路径(相对于 base)
// 默认:'./'
publicDir: 'public',
})
理解这些配置的关系:
root 决定了项目的根目录,Vite 会从这个目录开始解析文件。base 决定了静态资源的基础 URL 路径。publicDir 决定了静态资源目录的位置。
项目结构示例:
my-app/
├── index.html # root 目录下
├── public/ # publicDir 默认值
│ └── favicon.ico
└── src/
└── main.js
如果 base: '/app/'
- index.html 访问路径: http://localhost:5173/app/
- favicon.ico 访问路径: http://localhost:5173/app/favicon.ico
- main.js 访问路径: http://localhost:5173/app/src/main.js
路径解析
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
resolve: {
// 路径别名
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@assets': path.resolve(__dirname, './src/assets'),
},
// 导入时省略的扩展名
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
},
})
使用路径别名后,可以这样导入模块:
// 不使用别名
import Button from '../../../components/Button.vue'
// 使用别名
import Button from '@components/Button.vue'
开发服务器配置
export default defineConfig({
server: {
// 服务器端口
port: 3000,
// 自动打开浏览器
open: true,
// 允许外部访问
host: true, // 或指定 IP:'0.0.0.0'
// 启用 HTTPS
https: false, // 或传入 https 配置对象
// 热更新配置
hmr: {
overlay: true, // 显示编译错误遮罩
},
// 代理配置
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
// CORS 配置
cors: true,
// 浏览器控制台转发(Vite 8 新特性)
// 将浏览器控制台日志和错误转发到终端
forwardConsole: true,
// 自定义中间件
middlewareMode: false,
},
})
主机名安全配置
server.allowedHosts 用于控制 Vite 开发服务器允许响应的主机名,这是一个重要的安全配置:
export default defineConfig({
server: {
// 允许的主机名列表
allowedHosts: [
'example.com',
'.example.com', // 允许 example.com 及其所有子域名
],
// 注意:设置为 true 会允许任何主机名,存在安全风险
// allowedHosts: true, // 不推荐
},
})
安全警告:
- 默认情况下,
localhost、.localhost下的域名以及所有 IP 地址都是允许的 - 不要将顶级域名(如
.com)添加到允许列表,因为任何人都可以购买这些域名 - 设置为
true会允许任何网站通过 DNS 重绑定攻击向你的开发服务器发送请求,可能导致源代码泄露
也可以通过环境变量配置:
# 添加额外的允许主机名
__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS=example.com
构建配置
export default defineConfig({
build: {
// 输出目录
outDir: 'dist',
// 静态资源目录
assetsDir: 'assets',
// 是否生成 source map
sourcemap: false,
// 是否清空输出目录
emptyOutDir: true,
// 目标浏览器版本
target: 'es2015',
// 是否压缩代码
minify: 'esbuild', // 'esbuild' | 'terser' | false
// CSS 代码分割
cssCodeSplit: true,
// 资源内联限制(小于此值的资源会被内联为 base64)
assetsInlineLimit: 4096, // 4KB
// 块大小警告阈值
chunkSizeWarningLimit: 500, // 500KB
// Rollup 选项
rollupOptions: {
// 入口文件
input: {
main: path.resolve(__dirname, 'index.html'),
},
// 输出配置
output: {
// 入口文件命名
entryFileNames: 'js/[name]-[hash].js',
// 块文件命名
chunkFileNames: 'js/[name]-[hash].js',
// 资源文件命名
assetFileNames: (assetInfo) => {
const info = assetInfo.name.split('.')
const ext = info[info.length - 1]
if (/\.(png|jpe?g|gif|svg|webp|ico)$/i.test(assetInfo.name)) {
return 'img/[name]-[hash][extname]'
}
if (/\.(woff2?|eot|ttf|otf)$/i.test(assetInfo.name)) {
return 'fonts/[name]-[hash][extname]'
}
return '[name]-[hash][extname]'
},
},
},
},
})
CSS 配置
export default defineConfig({
css: {
// CSS Modules 配置
modules: {
scopeBehaviour: 'local',
localsConvention: 'camelCaseOnly',
},
// 预处理器选项
preprocessorOptions: {
scss: {
additionalData: `@import "./src/styles/vars.scss";`,
},
less: {
math: 'parens-division',
},
stylus: {
imports: [path.resolve(__dirname, './src/styles/vars.styl')],
},
},
// PostCSS 配置(会自动加载 postcss.config.js)
postcss: {
// 内联配置或配置文件路径
},
// 开发环境是否生成 source map
devSourcemap: false,
},
})
esbuild 配置
Vite 使用 esbuild 进行 JavaScript/TypeScript 转换:
export default defineConfig({
esbuild: {
// JSX 配置
jsxFactory: 'h',
jsxFragment: 'Fragment',
// 自动注入 JSX 辅助函数
jsxInject: `import React from 'react'`,
// 目标环境
target: 'es2020',
// 是否保留 console 和 debugger
drop: ['console', 'debugger'],
// 定义全局常量
define: {
__VERSION__: '"1.0.0"',
},
},
})
依赖优化
export default defineConfig({
optimizeDeps: {
// 预构建的入口
entries: ['./src/main.js'],
// 强制预构建的依赖
include: [
'vue',
'vue-router',
'pinia',
],
// 排除不需要预构建的依赖
exclude: ['@zougt/some-lib'],
// esbuild 选项
esbuildOptions: {
target: 'es2020',
},
},
})
Vite 8 新特性配置
Devtools(开发者工具)
Vite 8 内置了开发者工具选项,提供调试和分析 Vite 项目的深度洞察:
export default defineConfig({
devtools: true,
})
启用后,可以直接在开发服务器中访问 Devtools,获取以下功能:
- 项目结构分析
- 模块依赖关系图
- 构建性能分析
- 环境变量查看
TypeScript paths 自动解析
Vite 8 提供内置的 TypeScript 路径别名解析支持,无需手动配置 resolve.alias:
export default defineConfig({
resolve: {
// 自动读取 tsconfig.json 中的 paths 配置
tsconfigPaths: true,
},
})
启用后,Vite 会自动读取 tsconfig.json 中的 paths 配置。这有一定的性能开销,因此默认不启用。
emitDecoratorMetadata 支持
Vite 8 内置支持 emitDecoratorMetadata 选项,不再需要外部插件:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
这对于使用装饰器元数据的库(如 TypeORM、class-validator)非常有用。
Full Bundle Mode(实验性)
Vite 8 引入了实验性的 Full Bundle Mode,在开发时也进行模块打包:
export default defineConfig({
experimental: {
enableFullBundleMode: true,
},
})
适用于大型项目,可显著提升启动速度和减少网络请求。详见性能优化章节。
插件使用
Vite 插件扩展了构建流程的功能。插件可以是:
- 官方插件
- 社区插件
- 自定义插件
安装官方插件
# Vue 插件
npm install -D @vitejs/plugin-vue
# React 插件
npm install -D @vitejs/plugin-react
# React SWC 插件(更快的编译)
npm install -D @vitejs/plugin-react-swc
# Legacy 插件(支持旧浏览器)
npm install -D @vitejs/plugin-legacy
配置插件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [
// 使用插件
vue(),
// 插件可以配置选项
vue({
template: {
compilerOptions: {
// Vue 编译器选项
},
},
}),
],
})
条件使用插件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'
export default defineConfig(({ mode }) => ({
plugins: [
vue(),
// 只在生产环境使用 legacy 插件
mode === 'production' && legacy({
targets: ['defaults', 'not IE 11'],
}),
].filter(Boolean),
}))
完整配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig(({ command, mode }) => ({
// 基础配置
root: process.cwd(),
base: '/',
publicDir: 'public',
// 路径解析
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@views': resolve(__dirname, 'src/views'),
'@utils': resolve(__dirname, 'src/utils'),
'@assets': resolve(__dirname, 'src/assets'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
// 插件
plugins: [
vue(),
],
// 开发服务器
server: {
port: 3000,
open: true,
host: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
// 构建配置
build: {
outDir: 'dist',
sourcemap: mode === 'development',
rollupOptions: {
output: {
manualChunks: {
// 代码分割
vendor: ['vue', 'vue-router', 'pinia'],
},
},
},
},
// CSS 配置
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/vars.scss" as *;`,
},
},
},
// 依赖优化
optimizeDeps: {
include: ['vue', 'vue-router', 'pinia'],
},
}))
常见场景配置
SPA 单页应用
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: { '@': resolve(__dirname, 'src') },
},
server: {
port: 3000,
// SPA 常用的代理配置
proxy: {
'/api': {
target: 'http://api.example.com',
changeOrigin: true,
},
},
},
// SPA 通常不需要代码分割,可以禁用
build: {
cssCodeSplit: false,
},
})
MPA 多页应用
import { defineConfig } from 'vite'
import { resolve } from 'path'
import glob from 'glob'
// 自动发现所有 HTML 入口
const inputs = glob.sync('*.html').reduce((acc, file) => {
const name = file.replace('.html', '')
acc[name] = resolve(__dirname, file)
return acc
}, {})
export default defineConfig({
build: {
rollupOptions: {
input: inputs,
},
},
})
库开发配置
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'MyLib',
fileName: 'my-lib',
formats: ['es', 'umd', 'cjs'],
},
rollupOptions: {
// 外部化依赖
external: ['vue', 'lodash-es'],
output: {
globals: {
vue: 'Vue',
'lodash-es': '_',
},
},
},
},
})
Electron 应用配置
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
// Electron 主进程和渲染进程需要不同配置
// 渲染进程配置
base: './',
build: {
outDir: 'dist/renderer',
target: 'esnext',
},
server: {
port: 5173,
// 避免使用随机端口
strictPort: true,
},
})
微前端子应用配置
import { defineConfig } from 'vite'
export default defineConfig({
base: 'https://cdn.example.com/sub-app/',
build: {
// 输出到特定目录
outDir: 'dist',
// 生成 manifest 供主应用加载
manifest: true,
// 不要清空输出目录(避免删除其他子应用)
emptyOutDir: false,
},
})
Docker 容器化部署配置
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
// 使用环境变量动态设置 base
base: env.VITE_BASE_URL || '/',
server: {
// 允许容器内访问
host: '0.0.0.0',
port: 3000,
strictPort: true,
// 禁用 HMR(生产构建不需要)
hmr: false,
},
}
})
Monorepo 项目配置
import { defineConfig, searchForWorkspaceRoot } from 'vite'
export default defineConfig({
server: {
fs: {
// 允许访问工作区内的其他包
allow: [
searchForWorkspaceRoot(process.cwd()),
'../shared-components',
'../utils',
],
},
},
})
在配置中使用环境变量
加载 .env 文件
Vite deliberately 延迟加载 .env 文件直到用户配置解析完成后,因为加载的文件集取决于 root 和 envDir 等配置选项。
如果需要在配置中使用环境变量,可以手动加载:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
// 加载当前模式下的环境变量
const env = loadEnv(mode, process.cwd(), '')
return {
// 使用环境变量
server: {
port: env.VITE_PORT ? Number(env.VITE_PORT) : 3000,
},
define: {
__API_URL__: JSON.stringify(env.VITE_API_URL),
},
}
})
loadEnv 参数说明
loadEnv(mode, envDir, prefixes)
| 参数 | 说明 |
|---|---|
mode | 应用运行的模式 |
envDir | 环境文件所在的目录 |
prefixes | 环境变量前缀,默认为 "VITE_"。设置为空字符串 "" 加载所有变量 |
配置文件位置
可以通过 --config CLI 选项指定配置文件:
vite --config my-config.js
配置文件路径相对于当前工作目录解析。
写在最后
配置文件是定制 Vite 行为的核心。本章介绍了 defineConfig 的使用、条件配置、常用选项、插件配置以及环境变量的加载方式。
掌握这些配置选项后,你可以根据项目需求灵活调整 Vite 的行为,构建高效的开发环境。遇到不熟悉的选项时,可以查阅 Vite 配置参考 获取详细信息。