【实战】老项目焕发新生:从 Webpack 平滑迁移到 Vite 避坑全记录

前言

很多团队不敢升级 Vite,主要顾虑有两点:

  1. 构建差异:怕生产环境打包出问题,导致线上故障。
  2. 生态不兼容:怕老旧的 CommonJS 依赖库报错。

我的建议是:不要直接删除 Webpack 配置! 采用"双轨制"策略------保留 Webpack 用于生产构建,先在开发环境引入 Vite 享受秒级启动。待 Vite 极其稳定后,再彻底替换。

接下来,我们将一步步拆解这个过程。

一、 准备工作:依赖分析

在动工之前,先看一眼 package.json。如果你的项目包含以下特征,迁移难度会升级:

  • 使用了大量自定义的 Webpack Loader(需重写为 Vite 插件)。
  • 强依赖 require.context (需改为 import.meta.glob)。
  • 使用了 Node.js Polyfill(如 Buffer, process 等,在浏览器端缺失)。

二、 第一步:环境与入口改造

1. 安装 Vite

bash 复制代码
npm install vite @vitejs/plugin-vue (如果是Vue项目) --save-dev
# 或者
npm install vite @vitejs/plugin-react (如果是React项目) --save-dev

2. 移动 index.html

这是 Webpack 用户最不习惯的一步。

  • Webpack : public/index.html (作为模板)
  • Vite : 项目根目录 index.html (作为入口)

你需要把 index.html 移到根目录,并手动注入入口 JS:

html 复制代码
<!-- 根目录 /index.html -->
<!DOCTYPE html>
<html lang="en">
<body>
  <div id="app"></div>
  <!-- 必须加上 type="module" -->
  <script type="module" src="/src/main.js"></script>
</body>
</html>

3. 创建基础配置

新建 vite.config.js。为了兼容老项目的 @ 别名,我们需要配置 alias。

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' // 或 react
import path from 'path'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      // 兼容 Webpack 的别名习惯
      '@': path.resolve(__dirname, 'src'),
      '~': path.resolve(__dirname, 'node_modules') // 解决 scss 中 @import "~bootstrap"
    },
    // 如果你在导入文件时省略了后缀(不推荐,但老项目常见)
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
  }
})

三、 第二步:扫雷行动(常见报错与修复)

启动 npx vite,大概率你会看到满屏红字。别慌,我们一个一个杀。

坑位 1:require is not defined

Vite 基于 ESM,不支持 CommonJS 的 require

  • 场景const data = require('./data.json')

  • 解法 :全局替换为 import。

    javascript 复制代码
    import data from './data.json'
  • 特殊情况 :如果是动态 require,请使用 import.meta.glob(详见第二篇博文)。

坑位 2:process is not defined

老项目中代码里充斥着 process.env.NODE_ENV 或自定义变量。

  • 解法 :在 vite.config.js 中使用 define 进行全局替换。
javascript 复制代码
export default defineConfig({
  define: {
    // 简单粗暴地填充 process.env
    'process.env': {
      NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
      BASE_URL: JSON.stringify('/')
    },
    // 如果有 global 变量依赖
    'global': 'window' 
  }
})

坑位 3:JSX 在 .js 文件中报错

Webpack 的 babel-loader 可以配置在 .js 文件里写 JSX。但 Vite 使用 Esbuild,默认只支持在 .jsx.tsx 中解析 JSX。

  • 报错The JSX syntax extension is not currently enabled
  • 解法 A (推荐) :批量重命名文件,把 .js 改为 .jsx
  • 解法 B (配置):强制开启 JSX 支持(不推荐,影响性能)。
javascript 复制代码
// vite.config.js
export default defineConfig({
  esbuild: {
    loader: 'jsx', // 强制把所有文件当做 jsx 处理
    include: /src\/.*\.js$/,
    exclude: []
  }
})

坑位 4:CSS 深度选择器报错

老项目常用 /deep/ 写法,这已经废弃且 Vite 不支持。

  • 报错:Sass/Less 编译错误。
  • 解法 :全局替换。
    • /deep/ -> ::v-deep (Vue 2)
    • :deep(...) (Vue 3 标准写法)

四、 第三步:SVG 与图片处理差异

老项目可能使用 svg-sprite-loader 将 SVG 变成组件。Vite 中需引入 vite-plugin-svg-icons

Webpack 写法

javascript 复制代码
const req = require.context('./icons', false, /\.svg$/)
requireAll(req)

Vite 迁移写法

  1. 安装插件 npm i vite-plugin-svg-icons -D
  2. 配置:
javascript 复制代码
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'

plugins: [
  createSvgIconsPlugin({
    // 指定图标文件夹
    iconDirs: [path.resolve(process.cwd(), 'src/icons')],
    symbolId: 'icon-[dir]-[name]',
  }),
]
  1. 入口引入:import 'virtual:svg-icons-register'

五、 第四步:测试框架迁移 (Jest -> Vitest)

既然换了 Vite,原来的 Jest 可能会变得很慢(因为它还要走 babel 编译)。强烈推荐迁移到 Vitest

Vitest 和 Vite 共用同一套配置,无需额外编译,速度极快。

  1. 安装:npm i -D vitest
  2. 配置 vite.config.js
javascript 复制代码
export default defineConfig({
  test: {
    globals: true, // 开启 describe, it, expect 全局变量
    environment: 'jsdom',
  },
})
  1. 大部分 Jest 用法(expect, mock, spyOn)在 Vitest 中完全兼容,甚至 API 名字都一样。

六、 最终验证:双轨运行

package.json 中配置两个脚本:

json 复制代码
"scripts": {
  "serve": "vue-cli-service serve",  // 老 Webpack 启动
  "dev": "vite",                     // 新 Vite 启动
  "build:webpack": "vue-cli-service build",
  "build:vite": "vite build"
}

迁移策略总结

  1. 开发阶段 :全员使用 npm run dev (Vite),享受秒级热更新,极大提升开发幸福感。
  2. 测试/生产阶段 :暂时保留 npm run build:webpack
  3. 灰度切换 :当 Vite 在开发环境稳定运行 1-2 个月,且解决了所有构建时的 CSS/JS 兼容性问题后,尝试在测试环境使用 npm run build:vite
  4. 完全替换:测试环境无误后,正式切换生产打包命令,删除 Webpack 相关依赖。

全系列总结

至此,我们的**《Vite 深入浅出》**五篇系列博文圆满结束。

我们从**"为什么要用 Vite"的认知篇开始,经历了 "基础配置"的手把手教学,深入了 "双引擎架构"的底层原理,探索了 "插件开发"的高级玩法,最后落实到了"老项目迁移"**的实战落地。

前端构建工具的发展史,就是一部**"用算法换时间"**的历史。从 Grunt/Gulp 的任务流,到 Webpack 的全量打包,再到 Vite 的按需编译,我们一直在追求更快的反馈循环。

Vite 不仅仅是一个工具,它代表了现代 Web 开发的标准:Native ESM,极速,且轻量。

希望这一系列文章能成为你前端工程化道路上的一块垫脚石。去重构吧,去创造吧,把生命浪费在美好的代码逻辑上,而不是进度条的等待中!

相关推荐
web小白成长日记2 小时前
从零起步,用TypeScript写一个Todo App:踩坑与收获分享
前端·javascript·typescript
圣心3 小时前
Gemini 模型 介绍
前端
huangyiyi666663 小时前
前端-远程多选搜索框不能反显的问题解决
前端·javascript·vue.js·笔记·学习
敲敲了个代码3 小时前
让 Vant 弹出层适配 Uniapp Webview 返回键
前端·javascript·vue.js·学习·面试·uni-app
AOwhisky3 小时前
Ansible管理变量和事实(管理变量部分) & 部署文件到受管主机
前端·chrome·ansible
小二·3 小时前
Python Web 开发进阶实战:绿色软件工程 —— 构建低能耗、低碳排的可持续应用
开发语言·前端·python
hhcccchh3 小时前
学习vue第十四天 小白学父组件传递子组件(Props)
前端·vue.js·学习
派大鑫wink4 小时前
【Day32】Tomcat 服务器:安装、配置与 Web 应用部署
服务器·前端·tomcat
蜕变菜鸟4 小时前
数组参数赋值
linux·前端·javascript