用 AI 迁项目有多爽?我把 Webpack 迁 Vite 的全过程记下来了

用 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,所以第一步不是对配置,而是选型:

  1. 继续 Vue 2 → 用社区插件 vite-plugin-vue2(或同类维护中的 Vue 2 插件)
  2. 顺手升 Vue 3 → 迁移成本会再翻一倍,这次没选

我选了方案 1。Cursor 第一次给我的脚手架是 Vue 3 写法,我补了一句「项目是 Vue 2.7 + Webpack 4」,它才改成插件方案。版本和框架大版本,一定要先告诉 AI,不然后面所有配置翻译都会偏。

最小骨架大概是这样:

js 复制代码
// 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),三个用法:

  1. 贴报错问原因------完整报错 + 相关代码,让 Cursor 解释
  2. 翻译配置------把 Webpack 的某段配置贴进去,问「Vite 里对应怎么写」
  3. 检查遗漏------迁完之后让它扫一遍,看还有哪些 Webpack 特有写法

最关键的习惯 :报错不要只贴一行。要贴完整堆栈 + 出错的文件路径 + 相关代码。定位准确率完全不一样。

我一般这么问:

css 复制代码
项目: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) 的写法。

js 复制代码
// ❌ 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,它告诉我三件事:

  1. 业务代码里不要依赖 Node 的 process
  2. 要用 import.meta.env
  3. 自定义变量需要 VITE_ 前缀(MODE / DEV / PROD / BASE_URL 是内置的)
js 复制代码
// ❌ 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:

js 复制代码
// AI 第一版:在 "type": "module" 的项目里,__dirname 可能直接报错
alias: {
  '@': path.resolve(__dirname, 'src')
}

我项目的 Vite 配置是 ESM,__dirname 不可用。补了一句「vite.config.js 是 ESM」,它才改成:

js 复制代码
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 的处理和你的引入方式不匹配。可以:

  1. 升级到 echarts 5(ESM 友好)
  2. 用 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
js 复制代码
// 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 里怎么写」。最终可用的是:

js 复制代码
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 回了一堆:路径写错、文件不存在、服务器配置、缓存......全都不对。

后来换了问法,把目录和引用一起贴进去:

css 复制代码
项目结构:
- 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 之后才暴露。

html 复制代码
<!-- ❌ 多写了 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 帮到我的地方:

  1. 报错定位快 ------尤其是 xxx is not a function 这类隐蔽问题,能从模块格式解释
  2. 配置翻译省事------Webpack 片段贴过去,Vite 写法直接给,少翻文档
  3. 能补漏掉的细节 ------比如改完 .env 要重启 dev server

AI 坑我的地方:

  1. 方案版本对不上------不知道你装的 sass / echarts 具体版本
  2. 不知道项目背景------Vue 2 还是 3、ESM 配置、TS、能不能升级依赖,要你主动说
  3. 报错太泛时会瞎猜 ------一句 404 不够,要补结构和引用

我总结的 Cursor 使用习惯:

  • 报错贴完整堆栈,不要只贴一行
  • 先报框架大版本和关键依赖版本(Vue 2 / 3、echarts 4 / 5)
  • 方案要自己判断能不能上生产,不要照抄
  • 遇到「版本相关」的提示,先查本地 package.json,再追问 AI

可直接套用的 5 个 Prompt

css 复制代码
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 秒」值多少钱。你提重构,对面往往就一句------「先把需求做完」。

所以这篇文章不是怂恿你硬刚业务去迁生产。如果你暂时迁不了,可以这么用:

  1. 私底下练一遍------拷一份非核心模块或个人 demo,用 Cursor 把上面那几个坑走通。迁移能力本身是面试和跳槽时很吃香的经验,不一定非要写进公司仓库。
  2. 先攒证据再提 ------别一上来就说「我们该上 Vite」。用本机对比冷启动 / 热更新数字,再算人天成本(有 AI 辅助,两天左右能摸到可演示状态)。老板听得懂的是:省人时、少踩坑、风险可控,不是技术名词。
  3. 能局部就局部------新页面、新包、管理端里相对独立的一块,比「全站一夜切换」好推动得多。推不动全量,不等于完全没空间。
  4. 把这次当方法论------就算项目还停在 Webpack,文里那套「完整报错 + 版本号 + 自己判断能不能上线」照样能用在排障、升依赖、接新工具上。工具会换,判断力不会过期。

有机会迁,就按本文踩坑;没机会迁,就把流程跑熟。会迁的人,和只看过迁移教程的人,差的往往就是有没有亲手卡过那一下午。


总结

如果只记三件事:

  1. 用 AI 迁项目,定位报错比翻文档快,尤其是隐蔽的模块格式问题
  2. AI 不知道你的项目背景,Vue 大版本、TS、依赖版本、能不能升级都要主动告诉它
  3. AI 给的是「通用解」,能不能上生产,还是得你自己拍板

公司不让迁很正常;迁得成是运气加沟通,迁不成就把能力练在自己身上。

一句话:AI 负责加速定位,上线标准得你自己守;迁不迁得动,得看业务答不答应。


相关阅读

如果公司迁不了构建工具,日常更折磨人的往往是还原设计稿。我另写过一篇:蓝湖设计稿接 Cursor MCP,从选型、Cookie 过期,到样式方案对不上、AI 幻觉,整条链路的坑都记了------和本文一样,结论都是「能提效,但不是一键魔法」。

→ 蓝湖 MCP + Cursor:设计稿到代码的真实踩坑


参考

相关推荐
IT_陈寒1 小时前
Java中equals方法比了个寂寞?原来这才是正确的重写姿势
前端·人工智能·后端
默_笙1 小时前
🚓 分诊台与拆题术:让 RAG 学会判断和规划
前端·javascript
去伪存真1 小时前
Electron 自动化发布指南:GitHub Actions 跨平台打包全纪录
前端·electron
计算机魔术师1 小时前
OpenAI智能体失控闯进美国政府网站,53张用户图片外泄背后
前端
美好世界1 小时前
Codex 源码导读:第五部分——事件出口与多入口适配
架构
颜进强1 小时前
14 · NestJS ExecutionContext 执行上下文:守卫、拦截器、过滤器拿到的"同一个 context",为什么能力不一样?
前端·后端·ai编程
初学AI的小高1 小时前
LangGraph断点恢复与幂等执行实战
后端·架构
程序员Flycan1 小时前
🚀 跨域终结者:前端代理服务器(Proxy)原理解析与配置总结
前端
怕浪猫1 小时前
顶级模型一句话,AI 写出了能玩的 QQ飞车
前端·面试·github