用 AI 迁项目有多爽?我把 Webpack 迁 Vite 的全过程记下来了
摘要:Vue 2 + Webpack 4 冷启动 40 秒,我花两天迁到 Vite。很多个坑,有一半是贴完整报错给 Cursor 才定位的。AI 好用,但它的方案不一定能直接上生产。
40 秒是什么概念?
按下保存,起身倒水,坐下,杯子还没放稳,编译条才刚跑完一半。改一行样式,浏览器来回切三次才刷出来;同事问个问题,我得先等项目起来,才敢打开对应页面。
我那个 Vue 2 + Webpack 4 的老项目,冷启动 40 秒,热更新 3-5 秒。一天下来,光等编译的时间够写好几个页面。
想迁 Vite 很久了,一直拖着。这次不一样——我打算全程用 Cursor 陪着迁。
这篇文章不是完整的「Vite 迁移手册」,是AI 辅助迁移的踩坑记录:它帮到我的地方,也包括它坑我的地方。迁之前怎么把 Vue 2 跑起来,我会先交代清楚。
先说清楚:Vue 2 怎么在 Vite 里跑起来
官方 @vitejs/plugin-vue 面向的是 Vue 3。我的项目还是 Vue 2,所以第一步不是对配置,而是选型:
- 继续 Vue 2 → 用社区插件
vite-plugin-vue2(或同类维护中的 Vue 2 插件) - 顺手升 Vue 3 → 迁移成本会再翻一倍,这次没选
我选了方案 1。Cursor 第一次给我的脚手架是 Vue 3 写法,我补了一句「项目是 Vue 2.7 + Webpack 4」,它才改成插件方案。版本和框架大版本,一定要先告诉 AI,不然后面所有配置翻译都会偏。
最小骨架大概是这样:
// vite.config.js
import { defineConfig } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'
export default defineConfig({
plugins: [createVuePlugin()]
})
入口从 Webpack 的 html-webpack-plugin 换成项目根目录的 index.html,用 <script type="module" src="/src/main.js"> 挂上主文件;package.json 里 serve / build 换成 vite / vite build。
骨架跑通之后,才进入下面这些「业务代码和依赖」层面的坑。
我是怎么用 Cursor 迁项目的
我用的主要是 Cursor Chat(不是 Composer),三个用法:
- 贴报错问原因——完整报错 + 相关代码,让 Cursor 解释
- 翻译配置——把 Webpack 的某段配置贴进去,问「Vite 里对应怎么写」
- 检查遗漏——迁完之后让它扫一遍,看还有哪些 Webpack 特有写法
最关键的习惯:报错不要只贴一行。要贴完整堆栈 + 出错的文件路径 + 相关代码。定位准确率完全不一样。
我一般这么问:
项目:Vue 2.7 + 从 Webpack 4 迁到 Vite
报错如下:
[完整报错]
相关代码:
[出错的文件片段]
依赖版本(如有):[package.json 里相关包]
问:这个报错在 Vite 里通常是什么原因?怎么改?
报错只贴一行 xxx is not defined,AI 只能猜。贴完整信息,再带上框架版本,它才能从上下文推断。
坑 1:require 报错——require is not defined
坑:项目里用了 require('./xxx.png'),迁到 Vite 后直接报错。
AI 怎么帮我:
报错贴给 Cursor,它直接说「Vite 基于 ESM,浏览器端业务代码不支持 CommonJS 的 require」,并给出了 new URL(..., import.meta.url) 的写法。
// ❌ Webpack 时代
const img = require('./assets/logo.png')
// ✅ Vite
import img from './assets/logo.png'
// 动态路径
const img = new URL('./assets/logo.png', import.meta.url).href
这个坑 AI 定位得很快,不用翻文档。
坑 2:process.env 读不到——它压根不存在
坑:项目里到处是 process.env.VUE_APP_API_URL,迁到 Vite 后全是 undefined。
AI 怎么帮我:
我把「变量是 undefined」和 .env 文件内容一起贴给 Cursor,它告诉我三件事:
- 业务代码里不要依赖 Node 的
process - 要用
import.meta.env - 自定义变量需要
VITE_前缀(MODE/DEV/PROD/BASE_URL是内置的)
// ❌ Webpack / Vue CLI 时代
const api = process.env.VUE_APP_API_URL
// ✅ Vite
const api = import.meta.env.VITE_API_URL
它还提醒我:改完 .env 里的变量名后,要重启 dev server,不然不会生效。
这个细节我自己翻文档大概率会漏。尤其是改完没生效的时候,一般会怀疑配置写错了,其实只是 dev server 没重启。
改了半小时配置,最后发现重启一下就好——这种事最折磨人。
坑 3:路径别名失效——@ 指向变了
坑:Webpack 里配了 @ 指向 src,迁到 Vite 后 import xxx from '@/xxx' 报错。
AI 怎么帮我:
这次我直接把 Webpack 的 resolve.alias 配置贴给 Cursor,问「Vite 里对应怎么写」。它第一版给了 __dirname:
// AI 第一版:在 "type": "module" 的项目里,__dirname 可能直接报错
alias: {
'@': path.resolve(__dirname, 'src')
}
我项目的 Vite 配置是 ESM,__dirname 不可用。补了一句「vite.config.js 是 ESM」,它才改成:
import { defineConfig } from 'vite'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
})
但 AI 还是没主动提醒我:TS 项目里还要同步改 tsconfig.json 的 paths。这个我是后来发现 TS 报红才想起来的。
关键认知:AI 给的方案是「通用解」,但你的项目有特殊性(ESM 配置、TS、多环境、特定依赖),这些它不知道。要主动把项目背景补给它。
坑 4:CommonJS 依赖炸了——xxx is not a function
这是 AI 帮了大忙的地方。
坑:某个老库(echarts 4.x)在 Vite 里 import 出来不对,报错是 xxx is not a function,堆栈指向的是我的业务代码,不是那个库。
卡了一下午。
我一开始以为是版本问题,升小版本没解决;又怀疑引入方式,import * as、import echarts from、按需引入来回试,都不行。翻文档翻到怀疑人生——报错指的位置根本看不出问题。
后来把完整报错 + 引入代码 + package.json 里那个库的版本一起贴给 Cursor,它才从模块格式上定位:
这是 Vite 依赖预构建处理 CommonJS 的问题。echarts 4.x 是 CommonJS,esbuild 预构建时对 default export 的处理和你的引入方式不匹配。可以:
- 升级到 echarts 5(ESM 友好)
- 用
optimizeDeps.include把该依赖纳入预构建,必要时再配build.commonjsOptions
结果:第 2 个方案我试了能跑起来,但 echarts 是核心依赖,不想长期靠预构建兜底,最后还是升级到了 echarts 5,并改了一小部分破坏性 API。
关键认知:AI 定位这类「不报模块找不到、报函数不存在」的隐蔽问题特别强。但它给的方案要自己判断能不能用——它不知道你能不能升级依赖、团队愿不愿意改调用方。
坑 5:业务代码里用不了 Node API——比如 fs、path
坑:某个被业务 import 的工具文件里用了 fs.readFileSync,迁到 Vite 后报错。
AI 怎么帮我:
报错贴给 Cursor。需要纠正它一句不精确的说法:不是「Vite 的 dev server 跑在浏览器里」,而是——
vite.config.js、插件:跑在 Node,可以用fs/path- 被页面 import 的业务代码:会被打到浏览器,没有 Node 内置模块
它给的解决思路仍然有用:
- 构建时用 → 写在
vite.config.js或插件里 - 运行时用 → 说明这个逻辑不该出现在前端 bundle
- 只是想读静态文件内容 → 用
?raw/?url
// Vite 提供的内置处理方式
import content from './file.txt?raw' // 以字符串形式导入
import url from './file.png?url' // 以 URL 形式导入
但 AI 不知道的:这个逻辑到底该不该在前端跑,得我自己判断。它给的是「技术上怎么处理」,不是「业务上该不该这么干」。
坑 6:CSS 预处理器的配置格式变了
坑:Webpack 里配的 sass-loader 选项迁不过来。
AI 怎么帮我:
把 Webpack 的 sass-loader 配置贴给 Cursor,问「Vite 里怎么写」。最终可用的是:
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/variables.scss" as *;`
}
}
}
})
但 AI 给错过:它第一版用的是 @import "@/styles/variables.scss";,我项目里 dart-sass 比较新,@import 已经会报 deprecation 警告。改成 @use ... as * 才干净。
这也是「AI 给的方案版本对不上」的典型场景——它知道通用写法,但不知道你装的 sass 是哪个版本。
坑 7:public 资源 404——AI 在「报错太泛」时会瞎猜
坑:静态图放在 public/logo.png,页面里写成 /public/logo.png,迁到 Vite 后 404。
AI 没帮上忙的地方。
我一开始只丢一句「图片 404」,Cursor 回了一堆:路径写错、文件不存在、服务器配置、缓存……全都不对。
后来换了问法,把目录和引用一起贴进去:
项目结构:
- public/
- logo.png
- src/pages/Home.vue
里面写的是 <img src="/public/logo.png" />
Vue CLI / Webpack 时期这样能访问;Vite 里 404。为什么?
这次定位对了:Vite(以及多数 Webpack 模板)会把 public/ 里的内容拷到产物根目录,URL 里没有 /public 这一段。正确引用是 /logo.png。我之前那条路径,多半是历史项目里又套过一层目录,靠运气能访问;换 Vite 之后才暴露。
<!-- ❌ 多写了 public 这一段 -->
<img src="/public/logo.png" />
<!-- ✅ public 目录内容挂在站点根路径 -->
<img src="/logo.png" />
关键认知:报错太泛的时候,AI 需要更多上下文。 目录结构 + 实际引用 + 「以前在 Webpack 里怎么写的」,比单独丢一个 404 有用得多。
迁移后效果
| 指标 | Webpack | Vite |
|---|---|---|
| 冷启动 | 40s | 3s |
| 热更新 | 3-5s | < 500ms |
| 生产构建 | 2min | 40s |
数字是我本机测的体感级对比(同一台机器、同一份业务代码,启动到可交互 / 保存后热更新可见)。不同机器会有波动,但「冷启动从几十秒掉到几秒」这个量级是稳的。保存一下,热更新秒出——这个爽感,迁完那天我来回改了好几次样式就为了多感受一下。
代价:
- 迁移花了大约 2 天(含 echarts 升级和回归)
- 有几个老依赖必须升级
- 团队要重新熟悉 Vite 的配置和
import.meta.env
用 AI 迁项目的真实感受
AI 帮到我的地方:
- 报错定位快——尤其是
xxx is not a function这类隐蔽问题,能从模块格式解释 - 配置翻译省事——Webpack 片段贴过去,Vite 写法直接给,少翻文档
- 能补漏掉的细节——比如改完
.env要重启 dev server
AI 坑我的地方:
- 方案版本对不上——不知道你装的 sass / echarts 具体版本
- 不知道项目背景——Vue 2 还是 3、ESM 配置、TS、能不能升级依赖,要你主动说
- 报错太泛时会瞎猜——一句
404不够,要补结构和引用
我总结的 Cursor 使用习惯:
- 报错贴完整堆栈,不要只贴一行
- 先报框架大版本和关键依赖版本(Vue 2 / 3、echarts 4 / 5)
- 方案要自己判断能不能上生产,不要照抄
- 遇到「版本相关」的提示,先查本地
package.json,再追问 AI
可直接套用的 5 个 Prompt
1. 迁移前:项目是 Vue 2.7 + Webpack 4,把这段 Webpack 配置翻译成 Vite 配置(配置文件是 ESM):
[粘贴配置]
2. 报错时:Vue 2.7 项目从 Webpack 迁到 Vite,报错如下:
[完整堆栈]
相关文件:[粘贴代码]
问:原因是什么,怎么改?
3. 依赖问题:这个库是 CommonJS,版本 X.X.X,在 Vite 里报 xxx is not a function,
优先说清:optimizeDeps / commonjsOptions / 升级 ESM 版,各自利弊是什么?
4. 检查遗漏:根据 package.json + vite.config.js,列出还可能残留的 Webpack / Vue CLI 写法。
5. 配置对比:Webpack 的 [XXX 配置],在 Vite 里对应什么?我的约束是:[TS / 多环境 / 不能升某依赖]
每一条都把版本号和项目约束带进去,AI 给的建议才值得试。
说句实话:很多公司不会让你迁
写到这儿得泼盆冷水。
不是每个团队都能拿两天去做 Webpack → Vite。小公司更常见的是:需求排到年底、线上不能停、没人背锅、老板听不懂「冷启动从 40 秒到 3 秒」值多少钱。你提重构,对面往往就一句——「先把需求做完」。
所以这篇文章不是怂恿你硬刚业务去迁生产。如果你暂时迁不了,可以这么用:
- 私底下练一遍——拷一份非核心模块或个人 demo,用 Cursor 把上面那几个坑走通。迁移能力本身是面试和跳槽时很吃香的经验,不一定非要写进公司仓库。
- 先攒证据再提——别一上来就说「我们该上 Vite」。用本机对比冷启动 / 热更新数字,再算人天成本(有 AI 辅助,两天左右能摸到可演示状态)。老板听得懂的是:省人时、少踩坑、风险可控,不是技术名词。
- 能局部就局部——新页面、新包、管理端里相对独立的一块,比「全站一夜切换」好推动得多。推不动全量,不等于完全没空间。
- 把这次当方法论——就算项目还停在 Webpack,文里那套「完整报错 + 版本号 + 自己判断能不能上线」照样能用在排障、升依赖、接新工具上。工具会换,判断力不会过期。
有机会迁,就按本文踩坑;没机会迁,就把流程跑熟。会迁的人,和只看过迁移教程的人,差的往往就是有没有亲手卡过那一下午。
总结
如果只记三件事:
- 用 AI 迁项目,定位报错比翻文档快,尤其是隐蔽的模块格式问题
- AI 不知道你的项目背景,Vue 大版本、TS、依赖版本、能不能升级都要主动告诉它
- AI 给的是「通用解」,能不能上生产,还是得你自己拍板
公司不让迁很正常;迁得成是运气加沟通,迁不成就把能力练在自己身上。
一句话:AI 负责加速定位,上线标准得你自己守;迁不迁得动,得看业务答不答应。
相关阅读
如果公司迁不了构建工具,日常更折磨人的往往是还原设计稿。我另写过一篇:蓝湖设计稿接 Cursor MCP,从选型、Cookie 过期,到样式方案对不上、AI 幻觉,整条链路的坑都记了——和本文一样,结论都是「能提效,但不是一键魔法」。
参考
- Vite 官方文档 — 从 Webpack 迁移(cn.vite.dev/guide/migra…)
- Vite 官方文档 — 环境变量与模式(cn.vite.dev/guide/env-a…)
- Vite 官方文档 — 依赖预构建(cn.vite.dev/guide/dep-p…)
- vite-plugin-vue2(github.com/underfin/vi…)