Vite 是 Vue 生态官方推荐的下一代构建工具,它利用浏览器原生 ES Module 实现极速冷启动,配合 esbuild 进行预构建、Rollup 负责生产打包,让开发体验和生产构建都达到了很舒服的程度。Vue 3 项目几乎标配 Vite,掌握它的常用配置可以帮你解决 90% 的实际问题,而不需要掉进 Webpack 的配置黑洞。
以下所有配置都集中在项目根目录的 vite.config.js(或 .ts)中:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
// 所有配置在这里
})
路径别名:告别 ../../../ 地狱
在组件中引用公共模块时,相对路径会变得难以维护。通过 resolve.alias 设置路径别名,让导入路径永远清晰:
import path from 'path'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
}
}
})
然后在任何 .vue 或 .js 文件中就可以这样写:
import UserCard from '@/components/UserCard.vue'
import { formatDate } from '@utils/date'
为了让编辑器正确识别路径并给出自动补全,建议在 tsconfig.json 或 jsconfig.json 中同步添加:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
}
}
环境变量:区分开发/测试/生产
Vite 使用 dotenv 机制,根目录下创建 .env 系列文件:
.env:所有环境共享.env.development:开发环境(vite命令).env.production:生产环境(vite build命令)
变量必须以 VITE_ 开头才能在客户端代码中访问:
# .env.development
VITE_API_BASE_URL=http://localhost:3000/api
VITE_APP_TITLE=开发环境
在组件中通过 import.meta.env.VITE_API_BASE_URL 使用。这个值在构建时会被直接替换为字符串,使用时不需要做额外判断。
如果想在 vite.config.js 中根据环境切换行为,可以使用 defineConfig 中的 mode 参数:
export default defineConfig(({ mode }) => ({
base: mode === 'production' ? 'https://cdn.example.com' : '/',
// ...
}))
代理配置:解决跨域调试
开发时最常见的问题是前端端口(如 localhost:5173)请求后端接口(localhost:3000)时遇到 CORS 错误。Vite 的 server.proxy 可以完美解决:
export default defineConfig({
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
'/uploads': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
}
})
这样,前端代码中请求 /api/users 会被转发到 http://localhost:3000/users,完全绕开了浏览器同源策略。
插件体系:按需扩展能力
Vite 的插件基于 Rollup 插件接口,同时扩展了 Vite 专有钩子。Vue 官方插件 @vitejs/plugin-vue 已经提供了 .vue 文件的编译和 HMR 支持。
常用的第三方插件配置示例:
npm i -D @vitejs/plugin-legacy # 传统浏览器兼容
npm i -D unplugin-auto-import # 自动导入 API
npm i -D unplugin-vue-components # 组件自动按需引入
import legacy from '@vitejs/plugin-legacy'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
legacy({ targets: ['defaults', 'not IE 11'] }),
AutoImport({
imports: ['vue', 'vue-router'],
dts: 'src/auto-imports.d.ts'
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/components.d.ts'
})
]
})
AutoImport 让你不用再手动 import { ref, computed } from 'vue',直接在模板和 script 中使用;Components 则让你不用注册 Element Plus 组件,直接在模板写 <el-button> 就能自动发现并引入,且打包时会按需加载——最终产物中不会出现一个完整的组件库。
按需加载与预构建优化
Vite 在开发阶段会对 node_modules 中的依赖进行预构建(esbuild),将其转换成 ESM 格式并缓存。这个过程很快,通常无感。但如果你遇到了某些库与 ESM 不兼容导致开发卡住,可以通过 optimizeDeps 手动指定:
export default defineConfig({
optimizeDeps: {
include: ['moment/locale/zh-cn'], // 强制预构建
exclude: ['your-slow-lib'] // 排除预构建,让浏览器直接处理
}
})
对于按需引入,Vite 天然支持 Tree Shaking,只要你的代码使用 ESM 导入,不必要的代码就不会被打包。组件库配合 unplugin-vue-components 可以实现更彻底的按需加载。
构建分包策略:优化缓存利用率
单页面应用打包后,所有业务代码和第三方库混在一起会是一个巨大的 bundle,用户每次更新业务代码都要重新下载整个包。通过 rollupOptions.output.manualChunks 可以实现合理的分包,让第三方库的缓存命中最长时间:
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
'element-plus': ['element-plus'],
'utils': ['axios', 'lodash-es', 'dayjs']
}
}
}
}
})
这样会生成 vue-vendor.js、element-plus.js、utils.js 等独立 chunk,它们的内容极少变化,部署后浏览器长期缓存。你的业务代码频繁更新时,用户只需要重新下载变化了的小 chunk,首屏加载速度明显提升。
静态资源处理
Vite 对静态资源的处理非常直接:
- 图片、字体等:直接 import 会返回最终的公网路径,小于
build.assetsInlineLimit(默认 4KB)的资源会自动转成 base64 内联,减少 HTTP 请求。 - 放置位置:
public目录下的文件会被原样复制到打包目录的根路径,不经过编译,适合放 favicon、robots.txt 等。在代码中通过绝对路径/favicon.ico引用。 - 资源 CDN:设置
base配置项可以改变所有资源的基础路径,方便部署到 CDN:
export default defineConfig({
base: 'https://static.example.com/my-project/'
})
打包后,所有资源引用都会带上这个前缀,代码中的 /assets/logo.png 会变成 https://static.example.com/my-project/assets/logo.png。
实用的完整配置示例
最后,给出一个贴近真实项目的 vite.config.js,你可以把它作为起点按需调整:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig(({ mode }) => ({
base: mode === 'production' ? 'https://cdn.example.com' : '/',
resolve: {
alias: { '@': path.resolve(__dirname, 'src') }
},
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
},
plugins: [
vue(),
AutoImport({
imports: ['vue', 'vue-router'],
dts: 'src/auto-imports.d.ts'
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/components.d.ts'
})
],
build: {
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
'element-plus': ['element-plus']
}
}
}
},
optimizeDeps: {
include: ['axios']
}
}))
Vite 的配置哲学是“约定大于配置”,大多数时候你只需要调整这几个核心点,就可以让开发服务器飞快、打包产物干净合理。当遇到更特殊的需求时,再去查阅 Vite 官方文档或对应插件的配置说明,大概率都能找到现成的解决方案。