--- id: frontend.vite.scenario.webpack-to-vite title: 老项目从 webpack 迁移到 Vite:评估、步骤、风险和回滚 type: scenario domain: frontend stack: [vite, webpack] tags: [迁移, 构建工具, CommonJS, 环境变量, 灰度] level: intermediate prerequisites: [frontend.vite.dev-build-config, frontend.webpack.build-optimization] est_hours: 2 related: [frontend.vite.interview, frontend.webpack.interview] week: [7] --- # 老项目从 webpack 迁移到 Vite:评估、步骤、风险和回滚 ## 业务背景与问题 一个 5 年的 Vue 2 → Vue 3 后台项目(几百个页面)仍用 webpack 4 构建:开发启动要几分钟,改一行代码热更新要十几秒,团队抱怨效率低;依赖老旧,有安全漏洞告警。 ## 约束 - 不能停止业务需求开发,迁移要渐进。 - 有自定义的 webpack loader(处理内部 SVG 图标)和 `process.env.XXX` 的大量使用。 - 线上不能出问题,要可以回滚。 ## 方案设计 1. **评估**:列出 webpack 配置中所有的 loader / plugin,逐个找 Vite 对应方案(多数有现成插件);扫描代码中的 `require()`、`require.context`、`process.env`、`module.hot`。 2. **并行配置**:先新增 vite.config.ts,与 webpack 配置并存,开发者可以选择用哪个启动;CI 两种都构建。 3. **逐项替换**: - `require.context` → `import.meta.glob`; - `process.env.VUE_APP_XXX` → `import.meta.env.VITE_XXX`(批量替换 + 类型声明); - 自定义 loader → Vite 插件的 `transform` 钩子; - 别名、代理配置平移。 4. **验证**:页面冒烟测试(Playwright 跑核心流程);对比两份构建产物的体积和关键页面性能指标。 5. **灰度上线**:先上测试环境,再让部分流量使用新产物;保留 webpack 构建一个迭代周期,出问题可以切回。 ## 关键代码 ```ts // webpack:const modules = require.context("./icons", false, /\.svg$/); // Vite: const icons = import.meta.glob("./icons/*.svg", { query: "?raw", import: "default", eager: true }); // 自定义 loader 改写为插件 function svgIcon(): Plugin { return { name: "svg-icon", transform(code, id) { if (!id.endsWith(".svg?icon")) return null; return { code: `export default ${JSON.stringify(optimizeSvg(code))};`, map: null }; }, }; } ``` 可运行的 Vite 配置:[examples/vite-config](../examples/vite-config/)。 ## 取舍 | 选择 | 优点 | 缺点 | | --- | --- | --- | | **迁移到 Vite(本方案)** | 开发体验大幅提升、配置简单 | 迁移成本、部分 webpack 专有特性需要替代 | | 升级 webpack 5 + 缓存 + 更快的 loader(如 swc-loader) | 改动小 | 开发启动仍然慢于 Vite | | Rspack(兼容 webpack 配置的 Rust 构建工具) | 配置几乎不用改 | 生态兼容性需要验证 | ## 易错点 - 只验证开发模式,没有验证生产构建。 - 批量替换环境变量时遗漏了第三方库读取的 `process.env.NODE_ENV`(Vite 构建时会自动替换这个,但其他 `process.env` 引用不会)。 - 迁移后 chunk 的划分和文件名变化导致 CDN 缓存策略失效。 - 一次性切换,没有回滚方案。 ## 面试怎么讲 > “我主导过一个老项目从 webpack 迁到 Vite。先盘点配置和代码中的 webpack 专有用法,然后两套配置并存、CI 都构建,逐项替换 require.context、环境变量和自定义 loader;用 Playwright 跑核心流程冒烟,对比产物体积和性能指标;灰度上线,保留旧构建一个迭代。结果是开发启动和热更新明显变快(具体数字以你的项目实测为准)。”