Vite 配置详解
什么是 Vite
Vite(法语意为"快速的")是一个由 Vue.js 作者尤雨溪开发的构建工具,主要特点:
- 极速的开发服务器启动:基于 ES modules,无需打包
- 快速的热更新(HMR):只更新修改的模块
- 优化的生产构建:基于 Rollup 打包
核心概念
开发模式
Vite 在开发模式下使用原生 ES modules,浏览器直接加载模块,无需打包。
生产模式
生产环境使用 Rollup 进行打包优化,生成高效的静态资源。
基础配置
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({
// 插件配置
plugins: [vue()],
// 开发服务器配置
server: {
host: '0.0.0.0',
port: 3000,
open: true,
cors: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
// 构建配置
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: false,
minify: 'terser',
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]',
manualChunks: {
vue: ['vue', 'vue-router', 'pinia'],
vendor: ['axios', 'lodash'],
},
},
},
},
// 路径别名
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'components': resolve(__dirname, 'src/components'),
},
},
// CSS 配置
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`,
},
},
modules: {
localsConvention: 'camelCase',
},
},
// 环境变量前缀
envPrefix: 'VITE_',
});
插件系统
官方插件
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import react from '@vitejs/plugin-react';
import reactRefresh from '@vitejs/plugin-react-refresh';
export default defineConfig({
plugins: [
vue(), // Vue 3 支持
vueJsx(), // JSX 支持
// react(), // React 支持
// reactRefresh(), // React Fast Refresh
],
});
常用社区插件
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import { visualizer } from 'rollup-plugin-visualizer';
import { viteMockServe } from 'vite-plugin-mock';
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
vue(),
// 自动导入 API
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
resolvers: [ElementPlusResolver()],
dts: true, // 生成类型声明文件
}),
// 自动注册组件
Components({
resolvers: [ElementPlusResolver()],
dts: true,
}),
// Mock 数据
viteMockServe({
mockPath: 'mock',
enable: true,
}),
// Gzip 压缩
viteCompression({
algorithm: 'gzip',
ext: '.gz',
}),
// 打包分析
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
}),
],
});
环境变量
Vite 使用 dotenv 从环境目录中的文件加载额外的环境变量。
# .env
VITE_APP_TITLE=My App
VITE_API_BASE_URL=https://api.example.com
# .env.development
VITE_API_BASE_URL=http://localhost:3000
# .env.production
VITE_API_BASE_URL=https://api.production.com
// 使用环境变量
const apiUrl = import.meta.env.VITE_API_BASE_URL;
const title = import.meta.env.VITE_APP_TITLE;
// 类型定义 (env.d.ts)
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string;
readonly VITE_API_BASE_URL: string;
}
路径别名
// vite.config.js
import { resolve } from 'path';
export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@utils': resolve(__dirname, 'src/utils'),
},
},
});
// tsconfig.json 或 jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
}
}
CSS 处理
CSS Modules
// vite.config.js
export default defineConfig({
css: {
modules: {
localsConvention: 'camelCase', // 类名转换规则
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
});
<!-- Component.vue -->
<template>
<div :class="$style.container">Content</div>
</template>
<style module>
.container {
color: red;
}
</style>
CSS 预处理器
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`,
},
less: {
modifyVars: {
'@primary-color': '#1890ff',
},
},
},
},
});
PostCSS
// postcss.config.js
export default {
plugins: {
autoprefixer: {},
tailwindcss: {},
},
};
构建优化
代码分割
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
// 将 vue 相关库打包到一个 chunk
'vue-vendor': ['vue', 'vue-router', 'pinia'],
// 将工具库打包到一个 chunk
'utils': ['axios', 'lodash', 'dayjs'],
// 将 UI 库打包到一个 chunk
'ui': ['element-plus'],
},
},
},
},
});
依赖预构建
Vite 会自动预构建依赖,也可以手动配置:
export default defineConfig({
optimizeDeps: {
include: ['vue', 'vue-router'],
exclude: ['some-large-dependency'],
esbuildOptions: {
target: 'es2020',
},
},
});
压缩配置
import { defineConfig } from 'vite';
export default defineConfig({
build: {
minify: 'terser', // 'esbuild' | 'terser' | false
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
},
});
开发服务器
export default defineConfig({
server: {
host: '0.0.0.0', // 监听所有地址
port: 3000,
strictPort: false, // 端口被占用时自动尝试下一个可用端口
open: true, // 自动打开浏览器
cors: true, // 启用 CORS
https: false, // 启用 HTTPS
// 代理配置
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
configure: (proxy, options) => {
proxy.on('error', (err, req, res) => {
console.log('proxy error', err);
});
},
},
},
// HMR 配置
hmr: {
overlay: true, // 错误覆盖层
},
},
});
静态资源处理
导入静态资源
// 显式 URL
import logoUrl from './logo.png';
// 使用 ?url 后缀
import logoUrl from './logo.png?url';
// 使用 ?raw 后缀导入为字符串
import shaderString from './shader.glsl?raw';
// 使用 ?worker 后缀导入为 Web Worker
import Worker from './worker.js?worker';
// 使用 ?inline 后缀内联为 base64
import logoInline from './logo.png?inline';
公共资源目录
public 目录下的文件会被原样复制到输出目录的根目录。
// public/logo.png -> /logo.png
<img src="/logo.png" />
性能优化
预加载
<!-- 预加载关键资源 -->
<link rel="modulepreload" href="/src/main.js" />
异步组件
// 路由懒加载
const routes = [
{
path: '/home',
component: () => import('./views/Home.vue'),
},
];
图片优化
// 使用 vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin';
export default defineConfig({
plugins: [
viteImagemin({
gifsicle: { optimizationLevel: 7 },
optipng: { optimizationLevel: 7 },
svgo: {
plugins: [
{ removeViewBox: false },
{ removeEmptyAttrs: false },
],
},
}),
],
});
多页面应用
import { resolve } from 'path';
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
admin: resolve(__dirname, 'admin.html'),
},
},
},
});
库模式
构建库时使用:
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'MyLib',
fileName: (format) => `my-lib.${format}.js`,
formats: ['es', 'umd', 'cjs'],
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue',
},
},
},
},
});
工作原理
开发模式
- 依赖预构建:使用 esbuild 将 CommonJS/UMD 转换为 ESM
- 模块解析:浏览器直接请求 ES 模块
- 按需编译:只编译请求的模块
- HMR:只更新修改的模块
生产构建
- 代码转换:使用 esbuild 进行代码转换(比传统打包工具快 10-100 倍)
- 依赖打包:使用 Rollup 打包依赖
- 代码分割:自动进行代码分割
- 资源优化:压缩、Tree Shaking 等
常见问题
1. 路径别名不生效
确保在 tsconfig.json 或 jsconfig.json 中配置了 paths。
2. 环境变量未定义
确保环境变量以 VITE_ 开头,并使用 import.meta.env 访问。
3. 第三方库兼容性问题
在 optimizeDeps.include 中添加需要预构建的依赖。
4. 构建后路径错误
配置 base 选项:
export default defineConfig({
base: '/my-app/', // 部署在子路径时
});