工程化
新建 React 项目时,官方与社区主流工具为 Vite;全栈场景常用 Next.js。见 生态。
核心概念
React 官方不提供「创建项目」的工具,选择构建工具本质是在回答两个问题:要不要 SSR/全栈能力、要不要框架级的路由与数据获取约定。纯客户端 SPA(后台系统、工具类应用)通常选 Vite;需要 SEO、首屏 HTML、同仓库前后端的应用选 Next.js(或 React Router v7 的 Framework Mode,Remix 已并入其中,不再是独立框架)。
Vite + React
pnpm create vite my-app --template react-ts
cd my-app && pnpm install && pnpm dev
- 开发:原生 ESM + HMR。
- 生产:
vite build输出静态资源,可部署到任意静态托管。
配置见 Vite 文档。
// vite.config.ts 常见配置
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "node:path";
export default defineConfig({
plugins: [react()],
resolve: {
alias: { "@": path.resolve(__dirname, "src") },
},
server: {
proxy: {
"/api": "http://localhost:3000", // 开发期代理后端接口,规避 CORS
},
},
});
Create React App(CRA)
create-react-app 已进入维护模式,官方文档建议新项目选用框架或 Vite。已有 CRA 项目可继续维护,但不宜作为新起点。若需要迁移旧 CRA 项目到 Vite,通常步骤为:安装 vite + @vitejs/plugin-react,把 public/index.html 移到根目录并调整脚本引用方式,环境变量前缀由 REACT_APP_ 改为 VITE_,逐步替换 Webpack 专属配置(如 craco 自定义项)。
Next.js(全栈 / SSR)
Next.js 基于 React,提供:
- 文件系统路由(App Router)。
- 服务端组件(RSC)、SSR、SSG。
- API Routes / Server Actions 等。
适合需要 SEO、首屏 HTML、同仓库前后端的应用。纯客户端 SPA 仍可用 Vite。
// app/users/[id]/page.tsx(App Router,服务端组件)
export default async function UserPage({ params }: { params: { id: string } }) {
const user = await fetch(`https://api.example.com/users/${params.id}`).then((r) => r.json());
return <h1>{user.name}</h1>;
}
服务端组件在构建/请求时于服务器执行,不会把数据获取逻辑打进客户端 JS,有利于减少包体积并简化数据流;需要交互(useState、事件)的部分再拆出 "use client" 组件。
目录习惯(Vite SPA)
src/
components/
pages/
hooks/
App.tsx
main.tsx
按团队规模可引入 features/ 等分层,无唯一标准:
src/
features/
user/
components/
hooks/
api.ts
order/
shared/
ui/
hooks/
app/
router.tsx
main.tsx
「按功能(feature)分层」比「按类型(components/hooks/pages)分层」在中大型项目中更容易维护,因为一个功能的相关文件都聚在一起,删除功能时也更容易连带删除对应目录。
环境变量
Vite 仅暴露以 VITE_ 前缀的变量到客户端:
# .env
VITE_API_BASE=https://api.example.com
const base = import.meta.env.VITE_API_BASE;
勿将密钥写入 VITE_ 变量(会打进前端包)。
# .env.development / .env.production 按环境区分
# .env.development
VITE_API_BASE=http://localhost:3000
# .env.production
VITE_API_BASE=https://api.example.com
Vite 会根据 --mode 或 NODE_ENV 自动加载对应文件,vite build 默认使用 production 模式。
部署
pnpm build # 生成 dist/
静态产物可部署到 Nginx、Vercel、Netlify、对象存储 + CDN 等:
server {
listen 80;
root /var/www/my-app/dist;
location / {
try_files $uri $uri/ /index.html; # SPA 路由回退
}
}
Next.js 项目部署到 Vercel 最省心(官方产品,天然支持 App Router 特性);自建服务器部署需要 Node 运行时执行 next start 或使用 standalone 输出。
最佳实践
- 中后台/工具类纯前端项目默认选 Vite,不要为了「用了 Next.js 显得更高级」而引入不必要的 SSR 复杂度。
- 需要 SEO 的营销页/内容站优先选 Next.js(或 Astro 等专门的内容站方案)。
- 大项目按 feature 组织目录,而不是按文件类型平铺,便于代码定位与团队协作。
- 环境变量区分
.env.development/.env.production,敏感信息始终放后端或 CI Secrets,绝不进入VITE_/NEXT_PUBLIC_前缀变量。 - 从 CRA 迁移时先建一个并行的 Vite 项目跑通基础路由再逐步搬迁业务代码,避免一次性大改动。
常见坑
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 生产环境读不到环境变量 | 变量没有 VITE_/NEXT_PUBLIC_ 前缀 | 按框架约定加前缀,或在服务端读取无需暴露的变量 |
| 部署后刷新页面 404 | 静态托管未配置 SPA fallback | Nginx/托管平台配置 try_files 回退到 index.html |
| Next.js 服务端组件报错「不能使用 useState」 | 未加 "use client" 指令 | 需要交互状态的组件标记为客户端组件 |
| CRA 迁移到 Vite 后样式/资源路径失效 | public/ 引用方式、process.env 用法不同 | 按 Vite 约定调整静态资源与环境变量引用 |
| 开发期接口跨域报错 | 未配置代理,前端直接请求跨域后端 | 用 server.proxy 或后端开启 CORS |
延伸阅读
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| Vite 指南 | 中文 |
| Next.js 文档 | 英文 |
| create-react-app README | 维护说明 |
| Next.js:App Router | 服务端组件 |
| Vite:环境变量 | 配置说明 |
相关文章
渲染与协调
React 将组件渲染为虚拟 DOM 树,再协调(reconciliation)到浏览器 DOM。理解该过程有助于解释 key、memo 与性能优化。涵盖渲染流程、Fiber、startTransition、Suspense、最佳实践与常见坑。
TypeScript
React 官方推荐 TypeScript。类型主要落在 Props、事件、Ref 与 Hooks 返回值上。见 组件。
测试
React 组件测试推荐 React Testing Library(RTL):从用户可见行为断言,而非实现细节。运行器常用 Vitest 或 Jest。涵盖安装配置、查询优先级、异步测试、Mock 网络请求、最佳实践与常见坑。
构建与分包
通过代码分割与构建配置减小首屏 JavaScript 体积。涵盖 React.lazy/Suspense、路由级分割、Tree Shaking、Vite 生产构建、体积分析、最佳实践与常见坑。运行时优化见 runtime。
Effect 与副作用
useEffect 用于在组件渲染后执行与外部系统同步的逻辑(请求、订阅、手动改 DOM 等)。涵盖基本用法、依赖数组、适用/不适用场景、useLayoutEffect、最佳实践与常见坑。
状态管理
React 组件内 state 用 Hooks;跨组件共享状态可选 Context、Redux Toolkit、Zustand 等。见 Context Hook。
Series
react
9 / 16