携程前端训练营PC/H5开发(React)
React 基础 Demo、手搓 SSR 同构项目、以及 Next.js 企业级框架应用,代码仓库Fork自上游
项目导航与启动
本项目包含三个配套项目,分别对应不同的学习阶段,根据教程启动后可参照源码进行练习:
- react_study_demo: React 核心知识学习(Hooks, Router, Redux)
- react_ssr: 手动实现 React 服务端渲染(原理篇)
- react_ssr_next: 基于 Next.js 14 的企业级应用(实战篇)
快速启动
1 | # 1. React 基础学习 |
React基础与开发实战
基于 react_study_demo 项目,我们系统掌握了 React 18 的核心生态。
核心知识体系与实战演示
Hooks 实战 (src/pages/HooksPage.jsx):
- 通过
UseStateDemo展示了状态的基础管理与对象更新。 - 通过
CustomHookDemo演示了如何提取通用逻辑(如useCounter,useFetch)。 - 表格化对比了
useCallback与useMemo在性能优化场景下的不同用途。
组件通信 (src/pages/CommunicationPage.jsx):
- 父子通信: 演示了 Props 向下传递和回调函数向上传递。
- 兄弟通信: 展示了状态提升模式。
- Hooks 与 Class 混用: 演示了在存量项目中,新老组件如何互相调用。
路由管理 (src/pages/RouterPage.jsx):
- 实现了基础的声明式路由 (
<Routes>) 和编程式导航 (useNavigate)。 - 展示了从 URL 中提取动态参数 (
useParams) 和查询字符串 (useSearchParams) 的场景。
企业级 Axios 封装
在 src/api/request.js 与 AxiosDemo.jsx 中,我们实现了一套配置化的 HTTP 请求库:
统一拦截器:自动在 Request Header 中注入 Authorization Token,并在 Response 拦截器中统一处理 401/500 等错误码。
实战演示:
- 请求防抖/取消:在输入框连续输入时,利用
AbortController自动取消前一次未完成的请求。 - 请求缓存:对特定 GET 接口启用内存缓存,再次请求直接返回上次结果,减少服务器压力。
- 动态参数替换:通过配置
/api/user/:id,调用时仅需传入{ id: 123 }即可自动替换 URL。
React同构与SSR原理深度解析
基于 react_ssr 项目,我们手动从零搭建了一个 SSR 框架,为了解现代框架底层原理打下基础。
同构定义与挑战
同构 (Isomorphic) 指同一套代码既能在服务端运行渲染 HTML,也能在客户端运行接管页面交互。
核心挑战:服务端环境缺失 DOM/BOM API(如 window, document)。
在 src/shared/pages/Home.jsx 中,我们通过一个经典的环境判断案例解决了这个问题:
- 服务端渲染时:
renderEnv状态初始化为'server',页面显示 “SSR 渲染”。 - 客户端水合后:
useEffect执行(仅在浏览器端),将状态更新为'client',页面变为 “客户端已水合”。
SSR 核心三步流程
服务端渲染 (Render):
服务端使用 ReactDOMServer.renderToString(<App />) 将组件树转换为纯 HTML 字符串。
1 | // react_ssr/src/server/index.js |
嵌入模板 (Template):
在 src/server/template.js 中,将生成的 HTML 片段注入到完整的 HTML 骨架中,并引入客户端 JS 脚本 (bundle.js)。
1 | <div id="root">${appHtml}</div> |
客户端水合 (Hydration):
浏览器下载 JS 后,React 复用现有的 DOM 结构,并绑定事件监听器,使静态页面”活”过来。
1 | // react_ssr/src/client/index.jsx |
水合 (Hydration) 实战演示
在 src/shared/pages/Counter.jsx 页面中,我们可以直观地看到水合的作用:
- HTML 直出:服务端已经渲染出了计数器的初始数字
0。 - 事件绑定:只有当
bundle.js加载并执行hydrateRoot后,点击 “+” 按钮才会有反应。 - 水合检测:组件内部维护了一个
isHydrated状态,当useEffect执行时将其置为true,控制台输出具体的水合完成日志。
Next.js 框架实战
react_ssr_next 项目采用了 Next.js 14 (App Router),展示了生产环境下的最佳实践。项目结构清晰地展示了各项功能模块:
核心特性与目录结构
- App Router:
app/目录下的每个文件夹即一个路由,通过page.jsx定义页面,layout.jsx定义布局。 - Server Components (RSC):
app/page.jsx默认为服务端组件,直接在服务端执行逻辑,无 JS 传给客户端。 - Client Components: 在
components/client/page.jsx中,通过顶部声明'use client',演示了需要交互状态 (useState) 的组件写法。
数据获取策略
项目在 app/data-fetching 目录下对比了不同的数据获取方式:
- Server Fetching: 在 Server Component 中直接使用
async/awaitFetch 数据,演示了默认的 SSG (静态生成) 和 SSR (动态渲染) 缓存配置。 - Client Fetching: 在 Client Component 中使用
useEffect+fetch获取数据,适用于依赖用户交互的场景。
API Routes 实战
app/api-routes/page.jsx 及其配套的 app/api/hello/route.js 展示了如何构建后端接口:
- Route Handlers: 定义
GET,POST等具名函数来处理 HTTP 请求。 - 全栈能力: 演示了不仅可以写前端页面,还能直接编写处理数据库逻辑的 API 接口,实现全栈开发。
手搓 SSR vs Next.js
| 特性 | 手搓 SSR | Next.js |
|---|---|---|
| 路由 | 手动配置 React Router | 基于文件系统自动生成 |
| 数据获取 | 复杂 (Redux/Context 注水) | 简单 (Async Components) |
| 构建 | 繁琐 (双 Webpack 配置) | 零配置 (SWC/Turbo) |
| 适用场景 | 学习原理、特殊定制架构 | 生产环境、企业级应用 |
高可用Web架构及性能优化
分层架构
- 视图层: 浏览器、微信、React SSR、React SSR Hybrid、ReactNative(Android/iOS)、小程序
- 业务逻辑层: 与渲染框架解耦的核心业务逻辑、多语言SDK、埋点上报、位置服务、人脸识别
- 公共组件层: 开发联调工具、跨平台适配(Hybrid API、路由适配、UI组件)、UI自动化测试
- 底层框架层: React/Next.js、ReactNative、Taro、Redux/Mobx
- 支撑工具层: CI/CD、APM、日志/监控/报警、安全套件、工具平台
性能指标与优化
| 指标 | 定义 | 优化方案 |
|---|---|---|
| FP/FCP | 首次绘制/内容绘制 | 内联关键 CSS, 延迟加载非关键 JS |
| FMP | 首次有效绘制 | 骨架屏, 核心接口预请求 |
瓶颈攻坚
- DNS/网络: CDN 分发, 开启 HTTP/2, DNS 预解析。
- 资源: 图片 WebP 化, 组件懒加载 (
React.lazy), 静态资源强缓存。 - 渲染: CSS 动画代替 JS 动画, 减少重排重绘, 虚拟列表。
- 接口: 接口合并, 关键数据 Redis 缓存, GraphQL 按需查询。
渲染模式选择指南
| 渲染方式 | 核心特点 | 实现方案 |
|---|---|---|
| 服务端渲染(SSR) | 首屏内容由后端渲染好再返回,提升FCP/FMP | 用Next.js/Remix框架,可做SSR缓存(如首页5分钟更新一次) |
| 预渲染 | 构建时提前渲染静态页面,适合静态内容多的页面 | 用prerender-spa-plugin |
| 同构渲染 | 一套代码同时支持SSR(首屏)和客户端渲染(交互),兼顾性能和体验 | 基于React同构方案实现 |
专项优化策略
- 无网优化:ServiceWorker 缓存首页,Localstorage 存储核心数据。
- 弱网优化:接口阶梯超时重试,图片资源自动降级。
课后作业:Quiz App
实战任务
创建一个简单的测验/问答应用。
参考 DEMO: https://react-quiz-app-demo.netlify.app/
功能要求
- 数据展示: 按顺序展示问题。
- 交互逻辑: 点击选项记录答案,支持上一题/下一题。
- 状态反馈: 答题结束后展示总分与正确率。
- 重置功能: 支持重新开始测验。
技术实现建议
State 设计:
1 | const [current, setCurrent] = useState(0); // 当前题目索引 |
组件拆分: <QuizCard>, <Option>, <ResultOverlay>
数据源: 建议将题目数据提取为单独的 json 文件或常量。

