4.6 KiB
4.6 KiB
id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week, order
| id | title | type | domain | stack | tags | level | prerequisites | est_hours | related | week | order | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| frontend.vite.dev-build-config | Vite 8:开发服务器原理、Rolldown 构建、环境变量、代理(含 SSE)、插件和拆包 | lesson | frontend |
|
|
intermediate |
|
2.5 |
|
|
1 |
Vite 8:开发服务器原理、Rolldown 构建、环境变量、代理(含 SSE)、插件和拆包
基于 Vite 8.3 编写并实际构建验证。Vite 8 的生产构建改为基于 Rust 编写的 Rolldown(Vite 7 及以前:开发时用 esbuild 预构建依赖,生产用 Rollup 打包);
build.rollupOptions改名为build.rolldownOptions(旧名仍可用但已标记弃用),拆包推荐output.codeSplitting。以官方文档为准:https://vite.dev/guide/ 、https://rolldown.rs/ 。
解释说明
为什么开发时快
- 开发:不打包。浏览器原生支持 ES 模块(
<script type="module">),请求哪个文件,Vite 就即时转换哪个文件(TS → JS、.vue→ JS)。第三方依赖会预构建(把 CommonJS 转成 ESM、把很多小文件合成一个),并强缓存。 - 热更新(HMR):文件修改后只让对应模块失效并重新请求,速度与项目大小基本无关。
- 生产构建:仍然要打包(减少请求数、tree shaking、压缩、拆包)。
常用配置
| 需求 | 配置 |
|---|---|
| 路径别名 | resolve.alias |
| 环境变量 | .env、.env.[mode];浏览器代码只能读取 VITE_ 前缀的变量(import.meta.env.VITE_XXX);配置文件中用 loadEnv |
| 开发代理 | server.proxy,解决开发时的跨域,支持 rewrite |
| 插件 | Rollup / Rolldown 兼容的插件钩子(resolveId、load、transform)+ Vite 专有钩子(configureServer、transformIndexHtml、handleHotUpdate) |
| 拆包 | Vite 8:build.rolldownOptions.output.codeSplitting.groups;动态 import() 自动拆包 |
| 兼容旧浏览器 | @vitejs/plugin-legacy |
Monorepo
pnpm workspace + Vite 是常见组合:多个应用共用组件库和工具包,workspace:* 引用本地包。
案例
AI 客服前端项目:开发时 /api 代理到本地 FastAPI,/stream 代理 SSE 流式接口;构建时注入版本号(便于排查线上问题对应哪个版本);Vue 运行时单独拆包,长期缓存。
代码示例
完整项目:examples/vite-config。已验证:tsc 类型检查通过;vite build 输出独立的 vendor-vue 和按需加载的 heavy chunk;开发服务器代理普通接口(/api/hello → 后端 /hello)和 SSE(每 0.5 秒一条,逐条到达,没有被缓冲)。
自定义插件——虚拟模块(vite.config.ts):
function buildInfo(version: string): Plugin {
const id = "virtual:build-info";
const resolved = "\0" + id;
return {
name: "build-info",
resolveId(source) { return source === id ? resolved : null; },
load(moduleId) {
if (moduleId !== resolved) return null;
return `export default ${JSON.stringify({ version, builtAt: new Date().toISOString() })};`;
},
};
}
代理和拆包:
server: {
proxy: {
"/api": { target: apiTarget, changeOrigin: true, rewrite: (p) => p.replace(/^\/api/, "") },
"/stream": { target: apiTarget, changeOrigin: true },
},
},
build: {
rolldownOptions: {
output: { codeSplitting: { groups: [{ name: "vendor-vue", test: /node_modules[\\/]@?vue/ }] } },
},
},
构建输出:
dist/assets/heavy-xxxx.js 0.08 kB
dist/assets/index-xxxx.js 2.54 kB
dist/assets/vendor-vue-xxxx.js 60.80 kB
易错点
- 把密钥放到
VITE_前缀的变量中:会被打包进浏览器代码,任何人都能看到。 - 以为开发代理在生产环境也生效:生产环境需要 Nginx 或网关转发。
- 开发正常、构建后报错:开发不打包,CommonJS 依赖、动态路径、大小写敏感的路径在构建时才暴露问题,提交前要跑一次
vite build。 - 照搬旧文章的
rollupOptions.output.manualChunks:Vite 8 中仍可用但已弃用,新项目使用codeSplitting。 - 拆包拆得太碎:请求数增加,反而变慢。
面试常问
- Vite 为什么比 webpack 开发时快?生产构建为什么还要打包?
- Vite 的环境变量是如何区分浏览器可见和不可见的?
- 写过 Vite 插件吗?说说钩子。