跳到主要内容

知识速查表

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 --ssrSSR 构建
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 }),
},
})

依赖预构建

为什么需要预构建?

  1. 兼容性:将 CommonJS/UMD 转换为 ESM
  2. 性能:合并大量小模块减少 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 {
// 仅客户端执行
}

常用插件

插件安装用途
Vuenpm i -D @vitejs/plugin-vueVue 3 支持
Vue JSXnpm i -D @vitejs/plugin-vue-jsxVue JSX 支持
Reactnpm i -D @vitejs/plugin-reactReact Fast Refresh
React SWCnpm i -D @vitejs/plugin-react-swcReact SWC 编译(更快)
React RSCnpm i -D @vitejs/plugin-rscReact Server Components
Legacynpm i -D @vitejs/plugin-legacy旧浏览器支持
PWAnpm i -D vite-plugin-pwaPWA 支持
SVGnpm i -D vite-plugin-svgrSVG 作为组件
检查器npm i -D vite-plugin-checkerTypeScript/ESLint 检查
自动导入npm i -D unplugin-auto-importAPI 自动导入
组件导入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 选项虽然默认支持 esbuildterser,但 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.esbuildOptionsoptimizeDeps.rolldownOptions
esbuild.*oxc.*
build.rollupOptionsbuild.rolldownOptions
worker.rollupOptionsworker.rolldownOptions
build.commonjsOptions无需配置(自动处理)

浏览器目标变更

浏览器Vite 7Vite 8
Chrome107111
Edge107111
Firefox104114
Safari16.016.4

esbuild 选项 → oxc 选项

esbuildoxc
jsxInjectjsxInject
jsx: 'automatic'jsx: { runtime: 'automatic' }
jsxFactoryjsx.pragma
jsxFragmentjsx.pragmaFrag
definedefine

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', // 必须明确指定
}
}
},
}

资源链接