Create React App 入门实战:一条命令创建 React 应用、模板选择与内置脚本原理
Create React App(CRA)是创建单页 React 应用的官方支持方式,提供一套“零配置”的现代构建方案。本文基于仓库中 getting-started 文档 的完整脉络展开:从三条创建命令的调用方式、模板(template)机制,到生成项目的目录结构与 start/test/build 三个内置脚本的实际行为。读完本文,你不仅能照着命令跑起来一个项目,还能理解 CLI 在底层如何解析参数、选择包管理器、安装依赖并落地模板文件。
一、CLI 的角色与运行前提
CRA 仓库是一个 monorepo,入门流程涉及三个核心包(见根目录 package.json 的 workspaces 配置):
| 包 | 目录 | 职责 |
|---|---|---|
create-react-app |
packages/create-react-app | 命令行入口,负责初始化项目并转发命令 |
react-scripts |
packages/react-scripts | 项目的本地构建工具,提供 start/build/test/eject 脚本 |
cra-template |
packages/cra-template | 基础模板,提供 public/ 与 src/ 初始文件 |
Node 版本要求
文档明确要求本地开发机 Node >= 14(服务器端不要求)。这不是文档的口头约定,而是入口脚本的硬性检查:index.js 会解析 process.versions.node,主版本低于 14 时直接报错退出。你可以在 nvm(macOS/Linux)或 nvm-windows 的帮助下在不同项目间切换 Node 版本。
当前版本的适用前提
仓库中 create-react-app 的 package.json 与 react-scripts 的 package.json 均为 5.1.0,engines.node 均为 >=14。另外两点值得注意的事实:
- 当前 CLI 的
init()首次运行时会打印一条弃用提示(见 createReactApp.js),并通过一个标记文件保证每次安装只出现一次; - CLI 启动时会先通过 npm registry 的
dist-tagsAPI 检查是否有更新版本(checkForLatestVersion),失败时回退到npm view create-react-app version慢速查询——这也是文档推荐使用npx(每次都拉取最新版本)而非全局安装的原因。
二、快速开始(Quick Start)
npx create-react-app my-app
cd my-app
npm start
npx 随 npm 5.2+ 提供,无需预先安装 CRA 本身。如果你的机器上曾通过 npm install -g create-react-app 全局安装过旧版本,文档建议先卸载(npm uninstall -g create-react-app 或 yarn global remove create-react-app),确保 npx 始终使用最新版本。
命令执行完毕后,打开 http://localhost:3000/ 即可看到应用。当准备部署生产环境时,用 npm run build 生成压缩产物(详见第五节)。
“开箱即用”的底气来自:你不需要自行安装或配置 webpack、Babel 等构建工具——它们被 react-scripts 预先配置好并隐藏起来。这一点可以从 react-scripts 的 package.json 的依赖清单看到:webpack@5、babel-loader、babel-preset-react-app、webpack-dev-server、jest、eslint-config-react-app、workbox-webpack-plugin 等全部作为其依赖锁定,业务项目无需感知。
三、创建应用的三种方式
文档给出三种等价入口:
npx(推荐)
npx create-react-app@latest my-app
@latest 显式锁定最新版本,规避本机缓存的旧 CLI。
npm
npm init react-app my-app
npm init <initializer> 在 npm 6+ 可用。
Yarn
yarn create react-app my-app
yarn create 在 Yarn 0.25+ 可用。
包管理器如何被“识别”
文档指出:CLI 会根据你用来运行命令的工具决定用 npm 还是 Yarn 安装依赖。源码印证了这一机制——createReactApp.js 中的 isUsingYarn() 通过检查 npm_config_user_agent 环境变量是否以 yarn 开头来判断。
这个判断会一路传导到模板初始化阶段,scripts/init.js 以项目内是否存在 yarn.lock 再次确认,并对产物做针对性改写:
package.json中的脚本命令会把npm run/npm前缀替换为yarn(init.js);- 模板自带的
README.md中的示例命令同样被替换为yarn(init.js)。
因此 npm init react-app 与 yarn create react-app 创建的最终项目在实际使用中确实会以各自包管理器的命令风格呈现。
完整的 CLI 参数
除了项目名(必填),createReactApp.js 用 commander 注册了以下选项:
| 参数 | 作用 |
|---|---|
--verbose |
打印额外日志(安装时追加 --verbose) |
--info |
打印环境调试信息(系统、Node/npm/Yarn 版本、相关 React 包版本) |
--scripts-version <alternative-package> |
指定非标准的 react-scripts 版本,支持具体版本号、tag(如 @next)、自定义 fork 包名、file: 本地路径、.tgz/.tar.gz 归档 |
--template <path-to-template> |
指定项目模板(下一节详解) |
--use-pnp |
启用 Yarn Plug'n'Play(仅 Yarn 1.12+ 支持,Yarn 2+ 不再需要该标志,见 createReactApp.js) |
四、选择模板(--template)
在创建命令后追加 --template [template-name] 即可从指定模板启动新项目;不指定时使用基础模板(cra-template)。
模板命名与解析规则
模板包统一命名为 cra-template-[template-name],但命令中只需提供 [template-name]:
npx create-react-app my-app --template [template-name]
getTemplateInstallPackage 函数实现了这套解析规则:
- 不带前缀的名字(如
typescript)会被补全为cra-template-typescript; - 支持
@scope/作用域前缀与@version版本后缀; - 支持
file:本地路径(相对当前工作目录解析)以及http(s)://的.tgz/.tar.gz归档。
在 npm 上搜索 cra-template-* 可以找到社区可用模板列表。
模板的兼容性门槛
模板功能依赖 react-scripts >= 3.3.0:createReactApp.js 中的 templatesVersionMinimum 为 3.3.0,若所选 react-scripts 版本不满足,CLI 会提示 --template 可能不兼容且不再把模板包加入依赖。
创建 TypeScript 应用
仓库自带 TypeScript 模板 cra-template-typescript(1.3.0),使用方式:
npx create-react-app my-app --template typescript
该模板的 template/ 目录提供 App.tsx、index.tsx、setupTests.ts 等初始文件。如果已有项目想追加 TypeScript,请转 Adding TypeScript 文档。
模板包内部结构
以基础模板 packages/cra-template 为例,其发布内容(files 字段)只有 template/ 目录与 template.json。模板行为由 template.json 描述:
{
"package": {
"dependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.1.0",
"@testing-library/user-event": "^13.2.1",
"web-vitals": "^2.1.0"
},
"eslintConfig": {
"extends": ["react-app", "react-app/jest"]
}
}
}
init.js 会读取该文件:package.dependencies 会在模板落地后作为额外依赖安装。注意根级的 dependencies 与 scripts 键自 CRA 5 起已废弃(见 init.js 的警告),自定义模板应使用新的 package 键,写法可参考 Custom Templates 文档。
五、生成结果:项目结构与初始化流程
运行任一创建命令后,当前目录下会生成名为 my-app 的目录(目录名需通过 checkAppName 的 npm 命名校验,且不能与 react、react-dom、react-scripts 同名),并安装全部依赖。以仓库当前基础模板 packages/cra-template/template 为准,实际产物结构为:
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── reportWebVitals.js
└── setupTests.js
文档中的示例目录曾列出
src/serviceWorker.js;从当前仓库的基础模板源码看,src/已改为包含reportWebVitals.js而不含serviceWorker.js,以模板实际文件为准。
创建过程的关键调用链
- 安全检查:isSafeToCreateProjectIn 检查目标目录,仅允许
.git、README.md等已知无害文件存在,并静默清理上次失败安装遗留的npm-debug.log/yarn-error.log; - 安装依赖:CLI 先安装
react、react-dom、react-scripts(及所选模板包),npm 路径使用--save-exact --no-audit(install),随后把react/react-dom改写为 caret 版本范围(setCaretRangeForRuntimeDeps); - 转发给本地 react-scripts:通过
executeNodeScript执行require('react-scripts/scripts/init.js').init(...)(createReactApp.js); - 模板落地(scripts/init.js):
- 写入四个默认脚本(可被模板的
package.scripts覆盖):{ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" } - 设置
eslintConfig为react-app(基础模板会再叠加react-app/jest,见上文template.json),并写入 browserslist 默认值; - 把模板
template/目录整体复制到项目根; - 将模板内的
gitignore文件重命名为.gitignore(若已存在则追加),规避 npm 将其改写为.npmignore的历史问题; - 若目标目录原有
README.md,会被重命名为README.old.md以免覆盖; - 若尚未在任何版本库中,自动执行
git init并创建首个提交Initialize project using Create React App(tryGitInit)。
- 写入四个默认脚本(可被模板的
无多余配置、无复杂目录结构——这正是文档所说 “only the files you need to build your app”。安装完成后进入项目:
cd my-app
六、内置脚本:start / test / build
新项目可直接运行以下内置命令(对应 init.js 结束时打印的命令清单,另含 eject)。
npm start(或 yarn start)
以开发模式运行应用,默认打开 http://localhost:3000。修改代码后页面自动热更新,构建错误与 lint 警告直接在控制台(及浏览器错误浮层)中呈现。
从 scripts/start.js 可以看到其行为细节:
- 首行即设置
NODE_ENV=development与BABEL_ENV=development(start.js); - 先校验
public/index.html与入口 JS 文件是否存在,缺失则直接退出(checkRequiredFiles); - 端口默认
3000,可用PORT环境变量覆盖;被占用时choosePort会询问换一个可用端口(start.js); - 绑定地址默认
0.0.0.0,可用HOST覆盖,设置HTTPS=true可启用 HTTPS。
npm test(或 yarn test)
以交互模式运行测试监视器,默认只运行自上次提交以来变更文件相关的测试。深入用法(快照测试、覆盖范围、非交互 CI 模式等)见 Running Tests 文档。
npm run build(或 yarn build)
为生产环境构建到 build 目录:以生产模式打包 React,产物经过压缩(minified),文件名包含内容哈希(hash),构建完成后即可部署。
eject
创建结束的输出中也提示了第四个命令:npm run eject(eject.js)会把构建配置、配置文件与脚本复制到项目目录,移除对 react-scripts 的依赖——执行后不可回退,建议先阅读 Advanced Configuration 文档 与 Alternatives to Ejecting 文档 再决定。
七、小结
CRA 的入门体验由三层协作完成:create-react-app CLI 负责环境检查(Node >= 14、npm >= 6 或 Yarn 1.12+)、包管理器识别与依赖安装;react-scripts 的 init 流程负责模板落地、脚本/ESLint/browserslist 配置写入与 git 初始化;cra-template 提供最小可运行的 public/ + src/ 文件集。掌握 --template、--scripts-version 等参数后,你可以在不 eject 的前提下自由定制项目起点;后续学习路径建议沿 custom-templates、adding-typescript 与 available-scripts 深入。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00