Vite 优化、踩坑汇总 + Webpack 迁移 Vite 实战

一、缓存 .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.envdefine 注入
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.envimport.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 优先工具链,迁移时把"插件思维"换成"内置能力 + 轻量插件"。
相关推荐
10share1 小时前
给 JSX 组件也来一份 Vue 式 scoped:jsx-scoped 让样式隔离不再靠自觉
前端·vue.js
小聪7081 小时前
elpis-core 领域模型驱动设计解析
前端
北城笑笑1 小时前
Vue 104 ,AI + ECharts + Word:大模型数据可视化报告生成实战(前端导出图文并茂 Word 文档)
前端·vue.js·word·echarts
创新技术阁1 小时前
FastapiAdmin 实战:二次开发前的准备(环境配置与项目启动)
前端·后端·fastapi
志尊宝1 小时前
Vue3 零基础每日笔记(010):watchEffect——用到谁就自动听谁的“懒人侦听器“
前端·vue.js·笔记
狗哥哥2 小时前
从“看对方向”到“做出行动”:投资决策卡
前端
拖孩2 小时前
一个人 + AI 做的小程序,一个月赚了 36 块
前端·后端·微信小程序
weixin_440730502 小时前
playwright实战-渠道应用操作
开发语言·前端·python
lhldsg2 小时前
从零构建智慧场馆解决方案小程序:开发全流程实战
java·前端·小程序