Vite 深度解析
Vite 利用浏览器原生 ESM 和 esbuild 预构建,实现了毫秒级冷启动和极速 HMR,彻底改变了前端开发体验。
为什么 Vite 这么快
传统打包工具(Webpack)开发模式:
所有模块 → Bundle → 启动 Dev Server
问题:项目越大,启动越慢(几十秒甚至更长)
Vite 开发模式:
启动 Dev Server(立即)
浏览器请求模块 → 按需转换 → 返回 ESM
依赖(node_modules)→ esbuild 预构建(Go 编写,极快)→ 缓存
源码(.vue/.tsx) → 浏览器请求时按需转换核心配置
ts
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
react(), // 或 vue()
],
// 路径别名
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
}
},
// 开发服务器
server: {
port: 3000,
open: true,
// 代理:解决开发环境跨域
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
},
// 构建配置
build: {
outDir: 'dist',
sourcemap: true,
// 代码分割
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
}
}
},
// chunk 大小警告阈值
chunkSizeWarningLimit: 500
},
// CSS 配置
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
},
modules: {
localsConvention: 'camelCase'
}
},
// 环境变量
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version)
}
}
})HMR 原理
文件变化 → Vite 服务器检测 → 计算最小更新范围 → 通过 WebSocket 推送
HMR 边界(HMR Boundary):
如果 Button.vue 变化:
Button.vue 接受自身更新 → 只替换 Button 模块
如果不接受 → 向上冒泡到 App.vue
如果没有边界 → 全页面刷新
Vue/React 插件自动处理 HMR,无需手动配置。
手动处理 HMR(自定义模块):
if (import.meta.hot) {
import.meta.hot.accept('./module.js', (newModule) => {
// 使用新模块
})
import.meta.hot.dispose(() => {
// 清理副作用
})
}插件开发
ts
// 自定义 Vite 插件
import type { Plugin } from 'vite'
function myPlugin(): Plugin {
return {
name: 'my-plugin',
// 构建钩子(与 Rollup 兼容)
buildStart() {
console.log('构建开始')
},
// 转换文件内容
transform(code, id) {
if (!id.endsWith('.ts')) return
// 转换代码...
return { code: transformedCode, map: sourceMap }
},
// 解析模块 ID
resolveId(id) {
if (id === 'virtual:my-module') {
return '\0virtual:my-module' // \0 前缀表示虚拟模块
}
},
// 加载虚拟模块
load(id) {
if (id === '\0virtual:my-module') {
return `export const data = ${JSON.stringify(generateData())}`
}
},
// Vite 特有钩子
configureServer(server) {
// 添加自定义中间件
server.middlewares.use('/custom', (req, res) => {
res.end('custom response')
})
},
handleHotUpdate({ file, server }) {
if (file.endsWith('.data')) {
// 自定义 HMR 处理
server.ws.send({ type: 'full-reload' })
}
}
}
}环境变量
bash
# .env 所有环境
# .env.local 所有环境,本地覆盖(不提交 git)
# .env.development 开发环境
# .env.production 生产环境
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
# 只有 VITE_ 前缀的变量才会暴露给客户端ts
// 使用环境变量
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 // 'development' | 'production'
// TypeScript 类型声明
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_TITLE: string
}性能优化技巧
ts
// 1. 预构建优化:手动指定需要预构建的依赖
export default defineConfig({
optimizeDeps: {
include: ['lodash-es', 'axios'], // 强制预构建
exclude: ['your-local-package'] // 排除预构建
}
})
// 2. 动态导入(代码分割)
const LazyComponent = lazy(() => import('./LazyComponent'))
// 3. 资源内联阈值
export default defineConfig({
build: {
assetsInlineLimit: 4096 // 小于 4KB 的资源内联为 base64
}
})
// 4. 预加载指令
// Vite 自动为动态导入生成 <link rel="modulepreload">
// 5. 库模式:打包为可发布的库
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
name: 'MyLib',
formats: ['es', 'cjs', 'umd'],
fileName: (format) => `my-lib.${format}.js`
},
rollupOptions: {
external: ['vue', 'react'], // 不打包 peer dependencies
output: {
globals: { vue: 'Vue', react: 'React' }
}
}
}
})总结
- Vite 开发模式利用原生 ESM,按需转换,无需打包
- esbuild 预构建 node_modules,比 Webpack 快 10-100 倍
- HMR 精确到模块级别,修改一个文件只更新该模块
- 生产构建使用 Rollup,输出优化的静态资源
- 插件系统兼容 Rollup 插件,生态丰富