知识速查表
CLI 命令
| 命令 | 说明 |
|---|---|
npm create vite@latest | 创建新项目(交互式) |
npm create vite@latest my-app -- --template vue | 使用模板创建项目 |
npx vite | 启动开发服务器 |
npx vite --port 3000 | 指定端口启动 |
npx vite --open | 启动并打开浏览器 |
npx vite --host | 允许外部访问 |
npx vite --force | 强制重新预构建依赖 |
npx vite --strictPort | 端口占用时直接退出 |
npx vite --cors | 启用 CORS |
npx vite --profile | 启动性能分析器 |
npx vite --debug | 显示调试日志 |
npx vite build | 生产构建 |
npx vite build --mode staging | 使用指定模式构建 |
npx vite build --watch | 监听文件变化重新构建 |
npx vite build --manifest | 生成构建清单 |
npx vite build --ssr | SSR 构建 |
npx vite preview | 预览生产构建 |
npx vite --config my-config.js | 使用指定配置文件 |
npx vite --configLoader runner | 使用模块运行器加载配置 |
npx vite --configLoader native | 使用原生运行时加载配置 |
支持的包管理器:npm、yarn、pnpm、bun、deno
Node.js 版本要求:20.19+ 或 22.12+
注意:
vite optimize命令已被废弃,预构建过程现在自动运行。
configLoader 选项说明
| 值 | 说明 |
|---|---|
bundle(默认) | 使用 Rolldown 将配置打包后加载,完整支持 TypeScript |
runner | 使用模块运行器即时转换,不创建临时文件,适合 monorepo |
native | 使用环境原生运行时加载,适合支持 TypeScript 的 Node.js 环境 |
项目结构
my-project/
├── index.html # HTML 入口
├── package.json # 项目配置
├── vite.config.js # Vite 配置
├── public/ # 静态资源(原样复制)
│ ├── favicon.ico
│ └── robots.txt
└── src/
├── main.js # 入口文件
├── App.vue # 根组件
├── assets/ # 资源(会被处理)
└── components/ # 组件
配置文件模板
基础配置
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,
open: true,
},
})
完整配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig(({ mode }) => ({
root: process.cwd(),
base: '/',
publicDir: 'public',
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@views': resolve(__dirname, 'src/views'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
},
server: {
port: 3000,
host: true,
open: 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'],
},
},
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/vars.scss" as *;`,
},
},
},
}))
环境变量
.env 文件
# .env # 所有环境
# .env.local # 本地(不提交 git)
# .env.[mode] # 特定模式
# .env.[mode].local # 特定模式本地
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
使用环境变量
// 访问环境变量
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
const baseUrl = import.meta.env.BASE_URL
TypeScript 类型
// vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_TITLE: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
路径别名
配置
// vite.config.js
import { resolve } from 'path'
export default defineConfig({
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'),
},
},
})
使用
// 导入组件
import Button from '@components/Button.vue'
// 导入工具
import { formatDate } from '@utils/date'
// 导入资源
import logo from '@assets/logo.png'
CSS 处理
预处理器
npm install -D sass-embedded # 或 sass
npm install -D less
npm install -D stylus
CSS Modules
/* style.module.css */
.container { padding: 20px; }
.title { font-size: 24px; }
import classes from './style.module.css'
// 使用
<div className={classes.container}>
<h1 className={classes.title}>Title</h1>
</div>
Scoped CSS (Vue)
<style scoped>
/* 只作用于当前组件 */
.container { padding: 20px; }
</style>
静态资源
资源导入
// 导入图片
import imgUrl from './img.png'
// 作为 URL
import assetUrl from './asset.js?url'
// 作为原始字符串
import shaderCode from './shader.glsl?raw'
// 内联为 base64
import inlineSvg from './icon.svg?inline'
public 目录
public/
├── favicon.ico
├── robots.txt
└── images/
└── logo.png
<!-- 使用根路径引用 -->
<img src="/images/logo.png" />
代理配置
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
},
})
Glob 导入
// 懒加载
const modules = import.meta.glob('./dir/*.js')
// 立即加载
const modules = import.meta.glob('./dir/*.js', { eager: true })
// 具名导入
const modules = import.meta.glob('./dir/*.js', {
import: 'setup',
eager: true,
})
// 排除文件
const modules = import.meta.glob([
'./dir/*.js',
'!**/bar.js',
])
动态导入
// 路由懒加载
const User = () => import('./views/User.vue')
// 条件加载
if (condition) {
const module = await import('./heavy-module.js')
}
// 动态路径
const module = await import(`./locales/${lang}.js`)
Web Workers
// 构造函数方式
const worker = new Worker(
new URL('./worker.js', import.meta.url),
{ type: 'module' }
)
// 查询后缀方式
import MyWorker from './worker?worker'
const worker = new MyWorker()
// 内联 Worker
import InlineWorker from './worker?worker&inline'
WebAssembly
// 导入并初始化
import init from './module.wasm?init'
init().then((instance) => {
instance.exports.main()
})
// 获取 URL
import wasmUrl from './module.wasm?url'
// 带导入对象
init({
env: {
memory: new WebAssembly.Memory({ initial: 256 }),
},
})
依赖预构建
为什么需要预构建?
- 兼容性:将 CommonJS/UMD 转换为 ESM
- 性能:合并大量小模块减少 HTTP 请求
配置选项
export default defineConfig({
optimizeDeps: {
// 强制预构建的依赖
include: ['vue', 'vue-router'],
// 排除预构建的依赖
exclude: ['my-linked-package'],
// 自定义 Rolldown 配置
rolldownOptions: {
target: 'es2020',
},
},
})
强制重新预构建
# 使用 --force 标志
npx vite --force
# 或删除缓存目录
rm -rf node_modules/.vite
SSR 配置
项目结构
src/
├── main.js # 通用应用代码
├── entry-client.js # 客户端入口
└── entry-server.js # 服务端入口
开发服务器
import { createServer as createViteServer } from 'vite'
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom',
})
app.use(vite.middlewares)
构建命令
{
"scripts": {
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.js --outDir dist/server"
}
}
SSR 配置选项
export default defineConfig({
ssr: {
// 不外部化的依赖
noExternal: ['my-lib'],
// 外部化的依赖
external: ['some-dep'],
// SSR 目标
target: 'node', // 或 'webworker'
},
})
条件逻辑
if (import.meta.env.SSR) {
// 仅服务端执行
} else {
// 仅客户端执行
}
常用插件
| 插件 | 安装 | 用途 |
|---|---|---|
| Vue | npm i -D @vitejs/plugin-vue | Vue 3 支持 |
| Vue JSX | npm i -D @vitejs/plugin-vue-jsx | Vue JSX 支持 |
| React | npm i -D @vitejs/plugin-react | React Fast Refresh |
| React SWC | npm i -D @vitejs/plugin-react-swc | React SWC 编译(更快) |
| React RSC | npm i -D @vitejs/plugin-rsc | React Server Components |
| Legacy | npm i -D @vitejs/plugin-legacy | 旧浏览器支持 |
| PWA | npm i -D vite-plugin-pwa | PWA 支持 |
| SVG | npm i -D vite-plugin-svgr | SVG 作为组件 |
| 检查器 | npm i -D vite-plugin-checker | TypeScript/ESLint 检查 |
| 自动导入 | npm i -D unplugin-auto-import | API 自动导入 |
| 组件导入 | npm i -D unplugin-vue-components | 组件自动导入 |
构建配置
export default defineConfig({
build: {
outDir: 'dist', // 输出目录
assetsDir: 'assets', // 资源目录
sourcemap: false, // Source map
target: 'es2015', // 目标浏览器
minify: 'esbuild', // 压缩工具(Vite 8使用Oxc)
cssCodeSplit: true, // CSS 分割
assetsInlineLimit: 4096, // 内联限制
chunkSizeWarningLimit: 500, // 警告阈值
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
},
},
},
},
})
注意:Vite 8 使用 Rolldown 作为打包器,配置选项与 Rollup 兼容。
minify选项虽然默认支持esbuild和terser,但 Vite 8 内部使用 Oxc 进行压缩。
多页面应用
// vite.config.js
import { resolve } from 'path'
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
about: resolve(__dirname, 'about/index.html'),
},
},
},
})
库模式
基本配置
// vite.config.js
import { resolve } from 'path'
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
fileName: 'my-lib',
formats: ['es', 'umd'],
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue',
},
},
},
},
})
多入口配置
export default defineConfig({
build: {
lib: {
entry: {
'my-lib': resolve(__dirname, 'src/index.ts'),
'utils': resolve(__dirname, 'src/utils/index.ts'),
},
name: 'MyLib',
},
},
})
package.json 配置
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.umd.cjs",
"module": "./dist/my-lib.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.umd.cjs",
"types": "./dist/index.d.ts"
},
"./style.css": "./dist/style.css"
},
"sideEffects": ["**/*.css"]
}
输出格式
| formats | 输出文件 |
|---|---|
['es', 'umd'] | my-lib.js, my-lib.umd.cjs |
['es', 'cjs'] | my-lib.js, my-lib.cjs |
['iife'] | my-lib.iife.js |
HMR API
if (import.meta.hot) {
// 接受自身更新
import.meta.hot.accept()
// 接受依赖更新
import.meta.hot.accept('./dep.js', (newModule) => {
console.log('updated:', newModule)
})
// 监听事件
import.meta.hot.on('vite:beforeUpdate', (data) => {
console.log('before update:', data)
})
// 清理副作用
import.meta.hot.dispose(() => {
clearInterval(timer)
})
}
package.json 脚本
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"build:staging": "vite build --mode staging",
"type-check": "tsc --noEmit"
}
}
浏览器支持
开发环境
目标为 esnext,使用 Baseline Newly Available 特性
生产环境(默认)
默认针对 Baseline Widely Available 浏览器(约 2.5 年前发布的浏览器):
- Chrome >= 111
- Edge >= 111
- Firefox >= 114
- Safari >= 16.4
最低支持(ESM)
- Chrome >= 64
- Firefox >= 67
- Safari >= 11.1
- Edge >= 79
旧浏览器支持
npm install -D @vitejs/plugin-legacy
import legacy from '@vitejs/plugin-legacy'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
})
常见问题
端口被占用
npx vite --port 3000
强制重新预构建
npx vite --force
# 或删除缓存
rm -rf node_modules/.vite
清空输出目录
build: {
emptyOutDir: true
}
相对路径部署
export default defineConfig({
base: './',
})
禁用 HMR
server: {
hmr: false
}
设置全局变量
export default defineConfig({
define: {
__VERSION__: JSON.stringify('1.0.0'),
},
})
CSP Nonce 配置
export default defineConfig({
html: {
cspNonce: 'YOUR-NONCE-VALUE',
},
})
生成依赖许可证
export default defineConfig({
build: {
license: true,
// 或指定文件名
license: { fileName: 'license.md' },
},
})
使用 Lightning CSS
export default defineConfig({
css: {
transformer: 'lightningcss',
},
build: {
cssMinify: 'lightningcss',
},
})
动态导入错误处理
window.addEventListener('vite:preloadError', (event) => {
event.preventDefault()
window.location.reload()
})
实用技巧
开发环境跳过类型检查加速启动
{
"scripts": {
"dev": "vite",
"type-check": "tsc --noEmit",
"build": "npm run type-check && vite build"
}
}
自动重启开发服务器
当修改 vite.config.js 后自动重启:
import { defineConfig } from 'vite'
export default defineConfig({
server: {
watch: {
// 监听配置文件变化
configFiles: true
}
}
})
优化大型项目启动速度
export default defineConfig({
server: {
// 预热常用文件
warmup: {
clientFiles: [
'./src/main.js',
'./src/App.vue',
'./src/router/index.js'
]
}
}
})
构建时生成版本信息
import { defineConfig } from 'vite'
import { readFileSync } from 'node:fs'
const pkg = JSON.parse(readFileSync('./package.json'))
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify(pkg.version),
__BUILD_TIME__: JSON.stringify(new Date().toISOString())
}
})
条件性启用插件
import { defineConfig } from 'vite'
import visualizer from 'rollup-plugin-visualizer'
export default defineConfig(({ mode }) => ({
plugins: [
// 只在分析模式下启用
mode === 'analyze' && visualizer({ open: true })
].filter(Boolean)
}))
运行命令:
vite build --mode analyze
配置开发代理绕过规则
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
// 特定路径不代理
bypass: (req, res, options) => {
if (req.url === '/api/health') {
return '/health.html'
}
}
}
}
}
})
Vite 8 新特性配置
内置 Devtools
export default defineConfig({
devtools: true,
})
Devtools 提供调试和分析 Vite 项目的深度洞察,直接在开发服务器中访问。
浏览器控制台转发
export default defineConfig({
server: {
forwardConsole: true,
},
})
将浏览器控制台日志和错误转发到开发服务器终端。当检测到编码代理时,此功能会自动激活。
TypeScript paths 自动解析
export default defineConfig({
resolve: {
tsconfigPaths: true,
},
})
自动读取 tsconfig.json 中的 paths 配置,无需手动配置别名。
Full Bundle Mode(实验性)
export default defineConfig({
experimental: {
enableFullBundleMode: true,
},
})
在开发时也进行模块打包,类似生产构建。适用于大型项目,可显著提升启动速度和减少网络请求。
依赖许可证生成
export default defineConfig({
build: {
license: true,
// 或指定文件名
license: { fileName: 'license.md' },
},
})
使用 Lightning CSS
export default defineConfig({
css: {
transformer: 'lightningcss',
},
build: {
cssMinify: 'lightningcss',
},
})
动态导入错误处理
window.addEventListener('vite:preloadError', (event) => {
event.preventDefault()
window.location.reload()
})
Vite 8 迁移速查
配置选项迁移
| 旧选项(已废弃) | 新选项 |
|---|---|
optimizeDeps.esbuildOptions | optimizeDeps.rolldownOptions |
esbuild.* | oxc.* |
build.rollupOptions | build.rolldownOptions |
worker.rollupOptions | worker.rolldownOptions |
build.commonjsOptions | 无需配置(自动处理) |
浏览器目标变更
| 浏览器 | Vite 7 | Vite 8 |
|---|---|---|
| Chrome | 107 | 111 |
| Edge | 107 | 111 |
| Firefox | 104 | 114 |
| Safari | 16.0 | 16.4 |
esbuild 选项 → oxc 选项
| esbuild | oxc |
|---|---|
jsxInject | jsxInject |
jsx: 'automatic' | jsx: { runtime: 'automatic' } |
jsxFactory | jsx.pragma |
jsxFragment | jsx.pragmaFrag |
define | define |
manualChunks → advancedChunks
// 旧配置(已废弃)
manualChunks: {
vendor: ['vue', 'vue-router'],
}
// 新配置
advancedChunks: {
groups: [
{ name: 'vendor', test: /\/(vue|vue-router)\// },
],
}
常见迁移问题
esbuild 依赖缺失:
npm install -D esbuild
CommonJS 导入问题:临时启用兼容模式
export default defineConfig({
legacy: {
inconsistentCjsInterop: true,
},
})
插件 moduleType 问题:
const plugin = {
name: 'txt-loader',
load(id) {
if (id.endsWith('.txt')) {
return {
code: `export default ${JSON.stringify(content)}`,
moduleType: 'js', // 必须明确指定
}
}
},
}