4.1 脚手架工具


文档摘要

4.1 脚手架工具 本节摘要:脚手架决定项目的起点。Create React App 曾经是默认答案,如今维护放缓、构建慢,已不再是新项目首选;Vite 靠原生 ES 模块的按需编译成为主流。本节对比两者全貌——目录结构、配置方式、性能与生态——并给出新项目与存量项目的选型路径。 本节目标 阅读完本节,你应当能够: 说出 CRA 与 Vite 各自的工作原理与性能差异 解释 CRA 为什么不再适合新项目 用 Vite 创建 React 项目并理解关键配置 判断存量 CRA 项目该不该迁移 一、问题与直觉:脚手架不是「选一个跑起来」那么简单 脚手架的选择在项目早期看似随意——「能跑就行」。但三个月后你会发现问题:要加一个功能,CRA 项目要先 eject 或装一堆 hack 插件;

4.1 脚手架工具

本节摘要:脚手架决定项目的起点。Create React App 曾经是默认答案,如今维护放缓、构建慢,已不再是新项目首选;Vite 靠原生 ES 模块的按需编译成为主流。本节对比两者全貌——目录结构、配置方式、性能与生态——并给出新项目与存量项目的选型路径。

本节目标

阅读完本节,你应当能够:

  1. 说出 CRA 与 Vite 各自的工作原理与性能差异
  2. 解释 CRA 为什么不再适合新项目
  3. 用 Vite 创建 React 项目并理解关键配置
  4. 判断存量 CRA 项目该不该迁移

一、问题与直觉:脚手架不是「选一个跑起来」那么简单

脚手架的选择在项目早期看似随意——「能跑就行」。但三个月后你会发现问题:要加一个功能,CRA 项目要先 eject 或装一堆 hack 插件;Vite 项目改一行配置就行。脚手架决定的是「后面每次遇到问题时的解决成本」。

另一个容易忽视的层面是团队心智:团队越熟悉某个脚手架的目录结构和配置方式,换工具的学习成本越高。所以脚手架不只是「技术选型」,还是「团队投入」——选之前想清楚「这是打算用一两年的工具」,别当一次性决定。这也是为什么「稳定压倒一切」——脚手架换得频繁,团队光适应环境就消耗大量精力。

第 1.2 节已经介绍过两者的基本用法,本节从生态视角看现状:CRA 由 Facebook 官方维护,一度是 React 的默认脚手架;Vite 由 Vue 作者尤雨溪开发,如今已是构建工具的主流。时间站在 Vite 这边。

二、CRA 的现状:曾经的标准答案

它解决了什么

CRA 的价值是「零配置起步」——预配置 Babel、Webpack、代码检查、测试环境,一条命令建出可运行的项目。它让 React 入门门槛大幅降低,也定义了「标准项目结构」。这套结构的价值至今仍在:很多现代脚手架的目录布局都能看到 CRA 的影子,它是 React 项目结构的「共同语言」。

它为什么退场

CRA 的问题在生态发展中暴露:

构建慢。底层是 Webpack 全量打包,项目一大,冷启动和热更新都变慢。现代开发对「秒级热更新」的期待,CRA 满足不了。

维护放缓。React 官方团队已把精力转向框架层(Next.js),CRA 的更新节奏明显放慢,对新工具(如 React 19)的适配滞后。

定制困难。需要自定义配置时只能 eject——把内部配置全部吐出来,从此自己维护,不可逆。而 Vite 的配置是「改文件」级别的。

维度 CRA Vite
底层 Webpack 开发期原生 ESM,构建期 Rollup
冷启动 全量打包,慢 按需编译,快
热更新 一般
配置 隐藏,eject 才能改 开放,vite.config 直接改
维护 放缓 活跃
生态 成熟 迅速补齐

三、Vite:为什么成为新主流

原理:开发不打包

Vite 的开发服务器不做「全量打包」,而是利用浏览器原生 ES 模块——浏览器请求哪个模块,Vite 就编译哪个。项目再大,冷启动也只编译被请求的部分。

两种构建方式的对比

两种构建方式的对比

这张图把两种构建的差异画在对比里:左侧 Webpack 是「一次打包所有」,右侧 Vite 是「用到多少编译多少」。和上面的 mermaid 流程图互补——那张看 Vite 的单次流程,这张看两种方式的整体差异。

使用

npm create vite my-app -- --template react cd my-app npm install npm run dev

生成的结构比 CRA 精简:index.html 在根目录,入口是 main.jsx,配置在 vite.config.js。

目录结构对比

两个脚手架的骨架放到一起看:

# CRA 结构 my-app/ public/ # 静态资源,index.html 在这里 src/ App.js # 根组件 index.js # 入口 App.css # 根组件样式 index.css # 全局样式 # Vite 结构 my-vite-app/ index.html # 入口在根目录(不是 public) vite.config.js # 配置文件 src/ App.jsx # 根组件 main.jsx # 入口 App.css index.css

最明显的差异:CRA 的 HTML 模板藏在 public 里,Vite 的 index.html 直接裸露在根目录——它是整个应用的真正入口,引用了 main.jsx。这种「入口透明」的风格贯穿 Vite 的设计:没有隐藏层,所见即所配。

环境变量的使用

项目里不同环境(开发、测试、生产)的配置(API 地址、开关)用环境变量管理:

// 在 .env 文件里定义 // VITE_API_URL=http://localhost:3000 // 组件里读取 const apiUrl = import.meta.env.VITE_API_URL;

Vite 用 import.meta.env.VITE_ 前缀读取环境变量,比 CRA 的 process.env.REACT_APP_ 前缀短且统一。注意 VITE_ 前缀是「暴露给前端」的约定——不带前缀的变量不会打进前端代码,避免密钥泄露。这一点在前后端分离的项目里尤其重要:前端代码会被任何人看到,密钥只能放服务端。

关键配置

import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], server: { port: 5173, }, build: { outDir: 'dist', }, });

插件系统是 Vite 扩展能力的入口——react 插件负责 JSX 转译,其他能力(代码检查、路径别名、代理)都以插件或配置项接入。遇到「CRA 里要装包 hack 的事」,Vite 里往往是改个配置或装个插件的事。

代理配置

开发时前端要请求后端接口,跨域问题用代理解决:

export default defineConfig({ server: { proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true, }, }, }, });

浏览器里请求 /api/xxx 会被 Vite 代理到后端地址,绕开跨域。这个配置是前后端联调的第一步,比 CRA 时代需要额外配置 proxy 中间件方便得多。注意代理只在开发服务器生效,生产环境的跨域要靠网关或后端配置解决——代理不是部署方案。

四、存量 CRA 项目要不要迁移

一个现实问题:团队手上已有 CRA 项目,要不要迁到 Vite?

不迁的理由:项目稳定运行、没有明显构建慢的痛点、迁移成本(配置对不齐、第三方插件兼容)大于收益。

迁的理由:构建慢到影响开发体验、需要 CRA 给不了的新能力、项目还在快速迭代期(迁移成本分摊在后续开发里)。

一个折中的判断:项目稳定就留着,项目活跃就值得迁。 迁移本身是「换构建层,不动业务代码」——React 代码和构建工具是解耦的,Vite 官方也提供迁移指南。但任何迁移都有回归风险,要配好测试再动手。

迁移的实操路径

如果决定迁移,按这个顺序推进风险最低:

第一,用 Vite 建一个空项目,把入口文件和依赖对齐。第二,逐个迁移 src 下的业务代码——组件、状态、工具函数基本原样可用,要改的主要是「import 方式」和「环境变量前缀」。第三,改配置文件:路径别名、代理、构建输出对齐旧项目。第四,跑测试和构建,验证产物一致。第五,灰度上线。

有一个容易被忽略的点:CRA 时代有些「隐形魔法」在 Vite 里不存在。比如 CRA 自动引入全局样式、自动处理 SVG 引用,Vite 需要显式配置。迁移时逐项对照「旧项目里哪些东西是 CRA 白送的」,否则上线后才发现样式或资源静默丢失。

构建产物对比

生产构建:CRA 用 Webpack 打包成 bundle,Vite 用 Rollup 打包。两者产物都能上线,但体积和分割策略有差异。Vite 默认按「动态 import」自动分包,CRA 需要手动配。配合第 3.1 节的代码分割,Vite 的项目通常首屏更小——这是 Vite 在生产侧的一个隐性优势,也是大项目对比构建工具时常被忽略的维度。

测试环境的差异

CRA 内置了 Jest 测试环境,Vite 默认不带。需要配 Vitest(Vite 生态的测试框架,API 兼容 Jest)或手动接 Jest。对已有测试的项目,这个差异在迁移清单里要占一格。Vitest 复用 Vite 的配置,不用单独配转译,迁移成本反而低。

⚠️ 常见坑:以为脚手架选型是一次性的。工具链会老化,两年回头看一次「当前项目的工具还是最优解吗」是值得的习惯。但别为了追新而频繁迁移——工具是服务的,稳定压倒一切。

💡 关键直觉:选脚手架看三个指标——冷启动速度、配置自由度、维护活跃度。2026 年的今天三个指标都指向 Vite;CRA 的价值是历史教科书和存量项目。新项目直接 Vite,别犹豫。

五、脚手架之外:项目模板的选择

Vite 建出来是「最小可跑项目」,真实项目还要加代码检查、格式化、测试、路径别名。现在团队常用「基于 Vite 的内部模板」或社区模板起步——一次配好,团队复用。这也引出一个决策:从零配 vs 用模板。用模板快但有黑盒,从零配慢但透明。我的建议是至少从头配一次理解每个配置的用途,之后再用模板提速。

模板里通常预置什么

一个「够用」的 Vite React 模板,除了基本依赖,通常会预置五样东西:

代码规范:ESLint + Prettier 配置,配好 React 插件与格式化规则。路径别名:@ 指向 src,组件 import 不再写一长串相对路径。测试环境:Vitest + Testing Library 配置,新组件顺手写测试。环境变量模板:.env.example 列出所有变量名,新人不用猜。CI 脚本:lint、test、build 串成一条命令,提交前跑一遍。

这五样预置的价值是「把团队约定固化进模板」——新成员 clone 下来就能按团队规范开发,不用逐个问「我们项目怎么跑测试」。

从零配一次的收益

用模板没问题,但「至少从零配一次」的收益值得说清楚:从零配让你知道每个配置项为什么存在。比如你亲手配过 server.proxy,就知道「开发时跨域为什么能通」;亲手配过路径别名,就理解「@ 指向哪、为什么别乱改」。这些理解在遇到「模板跑不起来」的诡异问题时是救命线索——你知道该查配置的哪一处,而不是对着报错干瞪眼。

脚手架选型之外的提醒

最后补一句关于「工具迷信」的话:脚手架和模板再方便,也只是起点。真正决定项目质量的,是项目里的代码组织与团队规范——第 5 章会讲。别花太多时间「比较脚手架」,够用就行;把精力留给业务代码和架构设计,它们的回报率高得多。

常见疑问快答

「Vite 的热更新为什么快?」 核心在「按需编译 + 依赖预构建」。开发期 Vite 不做全量打包,浏览器请求哪个模块才编译哪个——项目再大,改一个文件只重新编译这一个文件。依赖(node_modules 里的库)在启动时用 esbuild 预构建成 ESM 缓存,之后不再重新编译。对比 Webpack 的全量打包,Vite 把「改一行等几秒」变成「改一行等几百毫秒」。理解了「按需」两个字,很多 Vite 的配置行为(比如为什么有些文件没被处理)都能想通——不是它漏了,是它只处理被请求的部分。

「Vite 生产构建和开发是同一套吗?」 不是。开发期是「原生 ESM + 按需编译」,生产构建用的是 Rollup——因为原生 ESM 有性能开销(模块数量多时网络请求多),生产要打包合并。所以「开发期很快」和「生产产物质量」是两件事,各自有各自的机制。这带来一个实践含义:开发时看到的依赖解析、代码转译方式,和生产构建可能不同——遇到「开发正常、构建报错」,多半是「只依赖开发期特性」导致的。检查生产构建要在本地先跑一遍 npm run build 验证,别等上线才发现。

「Vite 项目怎么加路径别名?」 配置 resolve.alias。开发和生产都要配——alias 在开发期由 Vite 自己解析,生产期由 Rollup 走同一份配置。配置后组件里就能写 import Button from '@/components/Button',告别一长串相对路径。注意别只配 Vite 而不配编辑器/代码检查工具:路径别名需要 IDE 的 tsconfig(TS 项目)或 jsconfig 同步理解,否则编辑器里跳转失效、代码检查报「找不到模块」。配一处、全家同步,是路径别名的正确姿势——这也是 4.1 节「模板通常预置路径别名」里说的那件事。

「CRA 项目里的测试能直接搬到 Vite 吗?」 测试框架层面可以,环境层面要适配。CRA 内置 Jest 配置(babel-jest 转译、jsdom 环境、测试路径约定),Vite 不内置测试环境。两个迁移路径:一是装 Vitest——它复用 Vite 的转译和配置,API 兼容 Jest 的 describe/it/expect,迁移成本最低;二是继续用 Jest 但手动配 transform(把 Vite 的转译插进去)。绝大多数项目选 Vitest 更顺——和 Vite 共享配置、启动快、TypeScript 支持好。有大量存量 Jest 测试的话,评估一下工作量再决定,别为了「统一」硬迁。

本节速览

  • CRA 退场:构建慢、维护放缓、定制靠 eject
  • Vite 主流:开发期原生 ESM 按需编译,冷启动与热更新快
  • Vite 配置:vite.config.js 开放可改,插件系统扩展能力
  • 入口透明:index.html 裸露在根目录,无隐藏层
  • 环境变量:import.meta.env.VITE_ 前缀,不带前缀不会暴露
  • 代理配置:server.proxy 解决前后端联调跨域
  • 迁移判断:项目活跃值得迁,稳定就留着
  • 迁移五步:建空项目 → 迁代码 → 改配置 → 验证 → 灰度
  • 测试差异:Vite 默认不带测试环境,可用 Vitest 接续
  • 选型三指标:冷启动速度、配置自由度、维护活跃度
  • 模板 vs 从零:至少从头配一次,理解后再用模板提速

下一节看状态管理库生态——脚手架建好项目,状态管理决定数据怎么流动。Redux 全家桶、Zustand、Recoil 的周边配套与适用边界,第 3.3 节的选型框架在这里细化成库生态的完整视图,让你知道除了核心库本身,还有哪些中间件和工具值得用。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U