从 CRA 到 Vite:含 Cesium 的真实项目迁移实战记录

背景:CRA 时代的终结

随着 Create React App(CRA)被官方正式标记为废弃,大量依赖它的项目面临着构建工具的选型与迁移。本文记录了我将一个基于 CRA + CRACO + Cesium 的真实生产项目迁移到 Vite 的完整过程,包括踩过的坑、做过的优化,以及最终的性能收益。

为什么必须迁移?

CRA 多年来确实是 React 项目的默认选择,但它的短板在今天已经越来越明显:

表格

指标 CRA (Webpack) Vite (esbuild)
开发服务器冷启动 ~15s ~2s
HMR 热更新响应 ~1000ms ~200ms
底层构建引擎 Webpack esbuild / Rollup
维护状态 已废弃 活跃迭代

核心差距来自底层工具链:Vite 在开发阶段使用 esbuild 做依赖预构建,速度是 Webpack 的 10-100 倍;生产构建则基于 Rollup,产物体积更优。对于一个集成了 Cesium 这种重量级 3D 库的项目来说,构建速度的提升尤为明显。

迁移实战步骤

第一步:清理 CRA / CRACO 遗留物

先卸载所有 CRA 和 CRACO 相关依赖:

bash

bash 复制代码
npm uninstall react-scripts @craco/craco craco-cesium

然后更新 package.json 中的脚本命令:

json

json 复制代码
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
    "format": "prettier --write src/**/*.{js,jsx,ts,tsx,css,md,json,scss} --config ./.prettierrc"
  }
}

第二步:安装 Vite 与必要插件

bash

bash 复制代码
# Vite 核心与 React 支持
npm install --save-dev vite @vitejs/plugin-react

# Cesium 集成插件
npm install --save-dev vite-plugin-cesium
npm install cesium

注意:这里使用的是 vite-plugin-cesium(面向完整 cesium 包),如果你只用 @cesium/engine 核心库,更推荐上一篇文章介绍的 vite-plugin-cesium-engine。

第三步:编写 vite.config.js

这是迁移中最核心的配置文件,涵盖了 React JSX 转换、Cesium 集成、API 代理、路径别名和构建优化:

javascript

运行

javascript 复制代码
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import cesium from 'vite-plugin-cesium';

export default defineConfig(({ command, mode }) => {
  // 根据 mode 加载对应环境变量
  const env = loadEnv(mode, process.cwd(), '');

  return {
    plugins: [
      react({
        include: ['**/*.jsx', '**/*.js', '**/*.tsx', '**/*.ts'],
        babel: {
          plugins: [
            ['@babel/plugin-transform-react-jsx', { runtime: 'automatic' }]
          ]
        }
      }),
      cesium(),
    ],
    server: {
      proxy: {
        '/api': env.VITE_PORT_API_KEY,
        '/tilesets': env.VITE_PORT_API_KEY
      },
    },
    resolve: {
      alias: {
        '@': '/src',
      },
    },
    optimizeDeps: {
      exclude: ['react-virtualized'],
      include: ['prop-types'],
    },
    build: {
      assetsInlineLimit: 0,
      commonjsOptions: {
        include: [/react-virtualized/, /node_modules/],
      },
      chunkSizeWarningLimit: 1600,
    },
  };
});

几个关键配置的解释:

  • react({ include: [...] }) :让 Vite 同时处理 .js 和 .jsx 文件中的 JSX 语法,兼容老项目中混用的情况
  • optimizeDeps.exclude :react-virtualized 这类对 CommonJS 兼容有问题的库,排除预构建可以避免运行时报错
  • assetsInlineLimit: 0:Cesium 项目有大量静态资源,禁止内联为 base64,避免产物体积爆炸
  • chunkSizeWarningLimit: 1600:Cesium 本身体积很大,适当提高 chunk 告警阈值,避免构建日志被无意义警告刷屏

第四步:Cesium 静态资源的特殊处理

Cesium 运行时依赖大量静态文件(Workers、Widgets、Assets、ThirdParty),这是迁移中最容易出问题的环节。

虽然 vite-plugin-cesium 会自动处理大部分资源,但在某些复杂项目中,手动拷贝一份到 public 目录是最稳妥的方案:

bash

bash 复制代码
# 清理旧的拷贝
rm -rf public/cesium

# 从 node_modules 拷贝完整的 Cesium 构建产物
cp -r node_modules/cesium/Build/Cesium public/cesium

同时在 Vite 配置中定义基础路径:

javascript

运行

css 复制代码
define: {
  CESIUM_BASE_URL: JSON.stringify('/cesium'),
}

这样生产环境中 Cesium 会从 /cesium 路径加载所有资源。

第五步:HTML 入口文件改造

Vite 不支持 CRA 的 %PUBLIC_URL% 占位符,直接使用根路径即可:

html

预览

xml 复制代码
<!-- index.html -->
<link rel="icon" href="/favicon.ico" />
<script type="module" src="/src/index.jsx"></script>

注意:Vite 的 index.html 放在项目根目录,而不是 CRA 的 public/ 目录下。

第六步:.js 与 .jsx 文件重命名

CRA 允许在 .js 文件中写 JSX,但 Vite 默认只对 .jsx / .tsx 文件做 JSX 转换。如果你的老项目里有大量 .js 文件包含 JSX,可以用脚本批量重命名:

bash

bash 复制代码
#!/bin/bash
# rename-jsx.sh
echo "🔍 正在扫描 .js 文件中的 JSX 语法..."

find ./src -name "*.js" | while read file; do
  if grep -qE "</?[A-Za-z].*?>" "$file"; then
    newfile="${file%.js}.jsx"
    mv "$file" "$newfile"
    echo "✅ 已重命名: $file → $newfile"
  fi
done

echo "🎉 完成!所有含 JSX 的文件已重命名为 .jsx"

运行:

bash

perl 复制代码
chmod +x rename-jsx.sh
./rename-jsx.sh

更稳妥的做法是配合 vite.config.js 中的 react({ include: ['**/*.js'] }) 配置,这样即使不重命名也能正常工作,但重命名是更规范的长期方案。

第七步:环境变量迁移

Vite 要求客户端可访问的环境变量必须以 VITE_ 为前缀:

bash

ini 复制代码
# .env
VITE_FLAG_SMITH_API_KEY=abc123

使用方式从 CRA 的 process.env 改为:

javascript

运行

ini 复制代码
const key = import.meta.env.VITE_FLAG_SMITH_API_KEY;

第八步:静态资源处理

将图片、字体、Logo 等资源移到 /public 目录,引用时直接使用根路径:

javascript

运行

javascript 复制代码
// CRA 旧写法
require('../../assets/logo.png')

// Vite 新写法(资源在 public 目录下)
src="/logo.png"

如果老项目中 require() 用法太多不想逐个改,可以安装兼容插件:

bash

css 复制代码
npm install vite-plugin-commonjs --save-dev

但更推荐逐步替换为标准的 ES Module import 语法。

第九步:清理冗余依赖

bash

css 复制代码
npm uninstall html-webpack-plugin

迁移效果

完成以上步骤后,项目的开发体验有了质的飞跃:

  • 冷启动:15s → 2s,提升约 7.5 倍
  • HMR 热更新:1000ms → 200ms,提升约 5 倍
  • 配置复杂度 :从厚重的 Webpack + CRACO 配置,简化为一个几十行的 vite.config.js
  • Cesium 集成:通过插件 + 手动拷贝双保险,开发和生产环境都稳定运行

总结与建议

从 CRA 迁移到 Vite 不是简单的换个构建工具,而是一次工具链现代化的升级。对于集成了 Cesium 的项目,有几点经验值得注意:

  1. Cesium 资源路径是头号坑 :务必确认 CESIUM_BASE_URL 和实际资源输出路径一致,建议先用 debug 模式验证
  2. CommonJS 兼容库要单独处理 :react-virtualized、prop-types 这类老库可能需要 optimizeDeps 和 commonjsOptions 的特殊配置
  3. 渐进式迁移可行 :可以先让 .js 文件通过 include 配置兼容 JSX,再逐步重命名为 .jsx
  4. 产物体积要关注 :Cesium 本身很大,配合 manualChunks 做代码分割可以进一步优化加载性能

CRA 的时代已经结束,Vite 是当下 React 项目最稳妥的迁移方向。如果你还在维护 CRA 项目,建议尽早规划迁移。

相关推荐
墨林陌5 分钟前
AI 热点日报(2026-11-09):苹果代理式Siri曝光,Anthropic推进IPO,编码智能体实测翻车
前端
vipxieliang6 分钟前
JavaScript 迭代器与生成器:控制异步与惰性求值
前端·javascript
Hilaku15 分钟前
Event Loop 这篇你看完就不用再看别的了!
前端·javascript·程序员
恋猫de小郭1 小时前
Flutter 下 AOT 一个你怎么都想不出来的 Bug ,JIT 正常的计算,在 AOT 居然算错了
android·前端·flutter
晓得迷路了1 小时前
栗子前端技术周刊第 153 期 - Vitest 5.1、Remix v3.2、Node.js 27 Alpha...
前端·javascript·vite
Moment2 小时前
Harness Engineering 为什么是 AI Coding 的工程底座 ❓❓❓
前端·后端·面试
风骏时光牛马2 小时前
生成一个AI面试复盘标题,只需要一个标题,不需要其他的任何文本。
前端
红尘散仙11 小时前
谁说终端只能敲键盘?我用 Rust 给小说阅读器加上了鼠标
前端·后端·rust
陈随易12 小时前
C++26 草案被否,二十八年来头一回
前端·后端·程序员