创见博客
create-react-app 为什么被放弃,官方推荐用什么替代
七崽爱吃小饼干2026/09/17阅读 0专栏 webpack原理

如果你在 2018 年前后学 React,第一课多半是 npx create-react-app my-app。它曾经是搭建 React 项目的标准答案。但如今 React 官方已经弃用它,转而推荐框架或 Vite。这中间发生了什么?本文讲清 CRA 是什么、为什么被放弃、为什么它难以自己配置 webpack,以及官方推荐的方向和 Vite 的不同。

一、create-react-app 是什么

CRA 由 Facebook(现 Meta)在 2016 年推出,目标是「零配置上手 React」。它由两部分组成:

  • create-react-app:脚手架 CLI,负责生成项目模板。
  • react-scripts:项目依赖,封装了整套构建工具链——webpack、Babel、ESLint、Jest、PostCSS、webpack-dev-server 等。

使用方式极其简单:

bash
npx create-react-app my-app
cd my-app
npm start

你不用写一行 webpack 配置,就能得到编译、热更新、打包、测试、代码检查等能力。在「配置地狱」的年代,这是巨大的进步,也正是它流行的原因。

但它的设计里埋着一个根本矛盾:为了「零配置」,它把配置完全封死了。

二、为什么不再推荐用 CRA

1. 官方已经弃用

2025 年 2 月,React 团队正式将 CRA 标记为弃用(deprecated),react-scripts 不再积极维护。React 官方文档也早已把新项目指引改为「推荐使用框架,或在需要纯 SPA 时使用 Vite」。也就是说,CRA 不再是被推荐的起点。

2. 构建慢,且随项目变大越来越慢

CRA 基于 webpack,而 webpack 的开发模式是先打包再启动:

  • 项目越大,冷启动越慢,改一行代码的反馈也越慢。
  • 热更新(HMR)在大项目里会出现明显延迟。
  • 默认配置没有充分利用文件系统缓存、增量编译等现代优化。

在 Vite、Turbopack 等新工具把开发启动压到毫秒级的今天,CRA 的开发体验差距非常明显。

3. 技术栈陈旧

CRA 把 Babel、webpack、Jest 等一整套工具锁在 react-scripts 内部,版本更新滞后,用户无法选择更快的方案(如 SWC、esbuild)。想用新特性,只能等 CRA 升级——而它已经停止升级了。

4. 配置封闭,定制困难

这是最要命的一点,下一节单独展开。

5. 默认配置不再是最优

它默认引入较多 polyfill、不做极致的 Tree Shaking 和分包策略调整。在追求体积和性能的今天,这套默认值已经不够用。

三、为什么用 CRA 就「难以自己配置 webpack」

CRA 的核心卖点是「零配置」,代价就是你失去对构建的控制权。想改 webpack 只有三条路,且一条比一条难走:

1. 配置被藏起来了

webpack.config.js 不在项目里,而在 node_modules/react-scripts/config/ 下。你不改它,就只能用默认值;改了 node_modules,下次 npm install 就被覆盖。

2. eject 不可逆

npm run eject 会把配置释放到项目根目录,之后就能随意改。但它只能做一次、无法撤销:

  • 从此构建配置由你自己维护,升级要靠手动合并。
  • CRA 提供的封装红利(统一升级、一致性)全部消失。
  • 项目里会突然多出一大堆你没写过、也不完全理解的配置。

大多数团队并不想为此买单。

3. 覆写工具很脆弱

为绕开 eject,社区出现了 craco、react-app-rewired 等方案:它们读取 CRA 的原始配置再做修改。

js
// craco.config.js
module.exports = {
  webpack: { alias: { '@': path.resolve(__dirname, 'src') } },
};

问题在于,这些工具依赖 CRA 内部配置的具体结构。CRA(或它依赖的 webpack)一有变动,覆写就可能失效;而 CRA 本身又不再更新,等于把项目架在一个正在腐烂的地基上。

4. 想要深度优化时无从下手

现代构建常见的需求——精细的 splitChunks、runtimeChunk 缓存优化、Tree Shaking 调优、替换 Babel 为 SWC、自定义 loader——在 CRA 里要么做不了,要么得靠 hack。「零配置」在简单项目里是优点,在需要优化的项目里就成了枷锁。

四、官方推荐用什么替代 CRA

需要澄清一点:官方并没有「改用 Vite」作为唯一答案,而是给出了两条线:

  1. 全栈/生产级应用 → 用 React 框架,如 Next.js、Remix、Expo 等。
  2. 纯客户端 SPA / 想自己掌控 → 用 Vite(或 React Router 等)。

背后的判断是:

  • 构建工具应该交给专业的工具或框架,React 专注做好 UI 层。
  • CRA 试图「什么都管一点」,结果既不够轻(不如 Vite 快),也不够全(没有 SSR、路由、数据获取等框架能力)。
  • Vite 基于 esbuild + Rollup,开发体验和构建质量都更符合当前标准。

所以更准确的说法是:官方不再推荐 CRA,把起点让给了「框架」和「Vite」——其中 Vite 对应「纯 React 应用」的场景。

五、Vite 和 CRA 有什么不同

维度CRAVite
开发时构建webpack 先打包再启动原生 ESM,不打包,esbuild 预构建依赖
启动/HMR慢,随项目增大而恶化毫秒级,和项目规模基本无关
生产构建webpackRollup
配置隐藏,需 eject显式 vite.config.js,直接可改
扩展方式craco / eject(脆弱/不可逆)插件体系,Rollup 插件大多可用
环境变量REACT_APP_* + process.envVITE_* + import.meta.env
HTML 入口public/index.html根目录 index.html
代理src/setupProxy.jsserver.proxy
单元测试内置 JestVitest(需另装)
转译器Babelesbuild / SWC(可换)
维护状态已弃用活跃维护

最关键的两点差异:

1. 开发范式不同。 CRA 的开发服务器需要先把整个应用打包好;Vite 利用浏览器原生 ESM,按需提供模块,因此启动几乎瞬时,HMR 也极快。

2. 配置哲学不同。 CRA 是「我帮你配好,你别动」;Vite 是「给你一份干净的配置,你来管」。前者在简单场景省事,后者在需要定制时省心。

六、从 CRA 迁移到 Vite 的要点

迁移通常并不复杂:

  1. 装 vite、@vitejs/plugin-react,加 vite.config.js。
  2. index.html 放到根目录,脚本引用改为 <script type="module" src="/src/main.jsx">。
  3. 环境变量从 REACT_APP_* / process.env 改为 VITE_* / import.meta.env。
  4. 路径别名在 vite.config.js 配 resolve.alias,并同步 tsconfig.json 的 paths。
  5. 代理从 setupProxy.js 迁到 server.proxy。
  6. SVG 组件、Sass 等能力改用对应 Vite 插件。

React.lazy、动态 import()、CSS Modules 等用法基本无缝,改动集中在入口和配置层面。

小结

问题结论
CRA 是什么封装了 webpack 等工具链的 React 脚手架
为什么弃用构建慢、技术老旧、配置封闭、官方已停止维护
为什么难改配置配置被隐藏,eject 不可逆,覆写工具脆弱
官方推荐什么框架(Next.js 等)或 Vite
和 Vite 的区别开发不打包、启动快、配置显式可改

一句话:CRA 用「隐藏配置」换来了当年的上手便利,却在需要性能和定制时变成了束缚;Vite 则用「显式配置 + 原生 ESM」同时给了速度和自由——这正是它取代 CRA 成为 React 纯应用起点的原因。

评论
0/100