一、缓存 .vite 目录:依赖预构建异常处理
1.1 .vite 缓存是什么
预构建产物存放在 node_modules/.vite(可配置 cacheDir 换位置):
bash
node_modules/
└── .vite/
└── deps/ # 依赖预构建产物(esbuild 打包后的 ESM)
├── lodash.js
└── package.json # 记录依赖版本,用于判断是否需要重新预构建
作用:依赖未变化时启动直接复用缓存,跳过预构建,冷启动更快。
1.2 预构建异常的三大处理手段
| 问题 | 处理 |
|---|---|
| 依赖升级/新增后行为异常 | 删掉 node_modules/.vite 后重启,强制重新预构建 |
| 某个依赖预构建报错 | optimizeDeps.exclude: ["bad-package"] 排除该包 |
| 已知依赖想提前预构建 | optimizeDeps.include: ["lodash-es"] 预声明,首屏更快 |
ts
// vite.config.ts
export default defineConfig({
optimizeDeps: {
include: ["lodash-es", "axios"], // 启动时主动预构建,避免首屏等待
exclude: ["plugin-that-fails"], // 跳过有问题的依赖
},
});
快速命令 :
rm -rf node_modules/.vite && npm run dev是解决"预构建缓存异常"的第一板斧。
二、大型项目优化手段
2.1 开发期卡顿
| 手段 | 配置 |
|---|---|
| 预声明依赖 | optimizeDeps.include 提前预构建 |
| 限制 sourcemap | 开发期用 "eval" 或关闭,降低转换开销 |
| 缓存目录放固态盘 | cacheDir: "node_modules/.vite"(默认已在该位置) |
| 关闭无关插件 | 生产专用插件用 apply: "build" 限制,避免开发期空转 |
2.2 构建包体积过大
ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ["vue", "vue-router", "pinia"], // 框架单独分包,长缓存
echarts: ["echarts"], // 大库独立,按需加载
},
},
},
// 产物 gzip 压缩(配合 vite-plugin-compression 或部署层 Nginx gzip)
},
});
| 优化点 | 做法 | 效果 |
|---|---|---|
| 路由懒加载 | 路由组件用 () => import() |
首屏只加载当前页代码 |
| 第三方库分包 | manualChunks |
依赖不动则缓存命中,二次加载极快 |
| 压缩产物 | 构建层 gzip/brotli 插件 或 部署层压缩 | 传输体积降 60%~80% |
| 移除调试代码 | define: { "process.env.NODE_ENV": '"production"' } + 插件移除 console |
减小体积、避免泄漏 |
| 图片压缩 | 静态资源走 CDN 或构建期压缩 | 显著降体积 |
| 分析体积 | rollup-plugin-visualizer 生成可视化报告 |
定位体积大户 |
三、高频踩坑集合
3.1 静态资源路径
| 现象 | 原因 | 解决 |
|---|---|---|
| 打包后图片/字体 404 | 部署在子路径但 base 未设置 |
base: "/app/" 或相对 "./" |
public 下文件引用不到 |
用 import 引用了 public 文件 |
public 文件用绝对路径 /xxx.png,不经 import |
| 动态拼接路径不生效 | Vite 静态分析无法识别运行时拼接的资源 | 用 new URL("./img/" + name, import.meta.url).href 或放入 public |
3.2 环境变量打包失效
| 现象 | 原因 | 解决 |
|---|---|---|
| 打包后变量为 undefined | 变量没加 VITE_ 前缀 |
改名 + 重启 |
| 改了 .env 没反应 | dev-server 不监听 .env 变更 | 重启 npm run dev |
| 动态取变量失败 | import.meta.env[key] 不被静态替换 |
显式写死:import.meta.env.VITE_XX |
引入 process.env 报错 |
Vite 不注入 Node 环境变量 | 用 import.meta.env 或 define 注入 |
ts
// 兼容写法:把 process.env 指向 Vite 环境
export default defineConfig({
define: {
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
},
});
3.3 externals 处理(排除外部依赖)
场景:依赖由 CDN 提供、不打进产物:
ts
export default defineConfig({
build: {
rollupOptions: {
external: ["vue", "echarts"], // 不打包这些依赖
output: {
globals: { vue: "Vue", echarts: "echarts" }, // 运行时从全局变量取
},
},
},
});
html
<!-- index.html 通过 CDN 引入,产物不再包含 -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
库模式(
build.lib)开发时 external 更常用;应用项目一般交给分包 + CDN 预加载处理。
四、Webpack 项目迁移 Vite 完整步骤
4.1 步骤总览
flowchart LR
A[备份原项目] --> B[安装 Vite 依赖]
B --> C[创建 index.html 于根目录]
C --> D[编写 vite.config.ts]
D --> E[迁移静态资源与别名]
E --> F[迁移 Loader/插件到对应方案]
F --> G[改造环境变量与路径]
G --> H[npm run dev 逐个验证]
4.2 分步操作
第 1 步:备份并安装
bash
cp -r my-app my-app-backup # 备份
cd my-app
npm install -D vite @vitejs/plugin-vue # 按框架选择插件
第 2 步:创建根目录 index.html
html
<!-- 项目根目录 index.html(Webpack 里由插件生成,Vite 需要原生文件) -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>迁移项目</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script> <!-- 入口用模块方式引入 -->
</body>
</html>
第 3 步:删除 Webpack 相关文件
bash
rm webpack.config.js webpack.common.js webpack.dev.js webpack.prod.js
第 4 步:编写 vite.config.ts(参考本系列第 2 篇模板,替换对应配置)
第 5 步:迁移资源与别名
bash
# public 目录
mkdir public && mv public/xxx.png public/
# 静态资源(webpack 的 file-loader/url-loader 处理的文件)
mkdir src/assets && mv src/static/* src/assets/
第 6 步:迁移环境变量
bash
# 旧的 .env 中所有变量加 VITE_ 前缀(或改用 import.meta.env)
# 源码中 process.env.XXX → import.meta.env.VITE_XXX
第 7 步:逐页验证
bash
npm run dev # 开发环境跑通
npm run build # 生产构建通过
五、Webpack 配置 → Vite 对应方案映射表
| Webpack 配置 | Vite 对应方案 |
|---|---|
entry(多入口) |
build.rollupOptions.input(多页面) |
output.path / filename |
build.outDir / build.rollupOptions.output |
output.clean |
build.emptyOutDir(默认 true) |
resolve.alias |
resolve.alias(语法基本一致) |
resolve.extensions |
resolve.extensions |
| HtmlWebpackPlugin | 根目录原生 index.html |
| css-loader + style-loader | 内置 CSS 支持(自动处理) |
| sass-loader / less-loader | css.preprocessorOptions(仅需装 sass/less 本体) |
| postcss-loader + autoprefixer | postcss.config.js(Vite 自动识别) |
| file-loader / url-loader | 内置 asset 处理(assetsInclude 扩展) |
| DefinePlugin | define |
| clean-webpack-plugin | build.emptyOutDir |
| mini-css-extract-plugin | build.cssCodeSplit(默认开启拆分) |
| terser-webpack-plugin | build.minify(默认 esbuild,可换 terser) |
| devServer.proxy | server.proxy |
| webpack-dev-server | vite(内置 dev server + HMR) |
| ProvidePlugin(自动加载 $ 等) | define + 手动 import,或 unplugin-auto-import |
六、迁移避坑清单
| 坑 | 说明与对策 |
|---|---|
| 环境变量全丢 | process.env → import.meta.env,补 VITE_ 前缀,逐个 grep 替换 |
| 动态 require | 业务代码里 require() 在 ESM 下报错,改成 import 或动态 import() |
__dirname / __filename 不可用 |
用 import.meta.url + fileURLToPath 替代 |
| 路径别名找不到 | vite 配置 alias 的同时同步修改 tsconfig paths,否则 IDE/TS 报错 |
| CSS 全局变量失效 | 预处理器变量要在 css.preprocessorOptions 注入,组件里不能直接用 |
| 老浏览器白屏 | 加 @vitejs/plugin-legacy |
| 图片等资源 404 | 检查 base 与资源放置位置(public vs src/assets) |
| 首屏慢 | 依赖预构建 optimizeDeps.include + 路由懒加载 + 分包 |
| 个别依赖预构建崩溃 | optimizeDeps.exclude 排除后,改用动态 import 或 CDN external |
七、总结
- 缓存 :
.vite/deps是预构建产物,异常时删除重建、optimizeDeps.include/exclude精准控制; - 优化 :分包 + 懒加载 + 压缩三板斧,
rollup-plugin-visualizer定位体积大户; - 踩坑:路径(base/public)、环境变量(VITE_ 前缀 + 重启)、externals 三大高频区;
- 迁移:index.html 原生入口 → 配置映射表逐项替换 → 环境变量改造 → dev/build 双重验证;
- 核心心法:Vite 是"约定优于配置"的 ESM 优先工具链,迁移时把"插件思维"换成"内置能力 + 轻量插件"。