我是如何用 React 搞定第一个前端项目的(顺便爬了点数据)
上周五晚上十点半,我瘫在工位上刷着招聘网站。上海这鬼天气,梅雨季刚过,空调外机轰隆隆响得像在给我配 BGM。突然弹出一个消息:“小张,明天演示前能不能把那个数据看板改成交互式的?”——又是产品经理临时加需求。
我翻了个白眼,心里默念:又来?但转念一想,正好拿这个机会试试 React,毕竟之前光看源码、调性能,自己都没正经写过一个完整的应用。而且最近团队讨论要不要用 React 重构老后台系统,领导说“谁先跑通 demo 谁就带技术方案”,这不就是我的机会?
其实我一直是个后端偏重的开发者。平时不是在扒开源项目源码,就是在研究 V8 引擎怎么优化 JS 执行,或者给 Node.js 服务做火焰图分析。但架不住现在全栈是趋势啊!尤其我们组最近搞了个内部爬虫平台,后端用 Python + Scrapy 写得飞起,结果前端还是 jQuery + Bootstrap 3 的古董组合,UI 简直不忍直视。
测试同学每次提 bug 都带着表情包:“你这页面点三下才响应,是不是在等爬虫跑完一圈?”运维更是直接:“你这前端打包出来 5MB,CDN 都快扛不住了!”
行吧,是时候上 React 了。
从零开始:别被脚手架吓到
很多人一听说“React 入门”就想到 Webpack、Babel、ESLint……一套配置下来能劝退一半人。但说实话,现在官方工具 create-react-app(简称 CRA)已经足够傻瓜化了。
我在公司 Mac 上打开终端,敲下:
npx create-react-app data-dashboard
cd data-dashboard
npm start
几秒后浏览器自动打开 localhost:3000,熟悉的旋转 React logo 出现了。那一刻我差点热泪盈眶——终于不用手动配 webpack 了!
吐槽一句:CRA 默认没开 TypeScript,但如果你和我一样喜欢类型安全(毕竟写后端习惯了),可以直接用:
npx create-react-app data-dashboard --template typescript
不过这次为了快速验证,我就先用 JavaScript 开干。
第一个组件:别想着一步登天
我们的爬虫平台需要展示任务列表、状态、抓取数量等。我打算先做一个简单的任务卡片。
新建 src/components/TaskCard.js:
import React from 'react';
function TaskCard({ task }) {
return (
<div className="task-card">
<h3>{task.name}</h3>
<p>状态: {task.status}</p>
<p>已抓取: {task.count} 条</p>
</div>
);
}
export default TaskCard;
然后在 App.js 里引入:
import TaskCard from './components/TaskCard';
function App() {
const mockTasks = [
{ id: 1, name: '新闻爬虫', status: 'running', count: 1243 },
{ id: 2, name: '电商价格监控', status: 'completed', count: 8976 }
];
return (
<div className="App">
<header className="App-header">
<h1>爬虫任务看板</h1>
{mockTasks.map(task => (
<TaskCard key={task.id} task={task} />
))}
</header>
</div>
);
}
跑起来一看,界面虽然丑,但数据能动态渲染了!这时候我突然意识到:React 的核心不是框架多牛,而是让你用组件思维去拆解 UI。以前写 jQuery 是“操作 DOM”,现在是“描述 UI 应该长什么样”。
联调后端:别忘了你还有个 API
Mock 数据终究是假的。我们的爬虫平台后端早就有 REST API 了,比如 GET /api/tasks 返回任务列表。
我用 useEffect + fetch 拉真实数据:
import { useState, useEffect } from 'react';
function App() {
const [tasks, setTasks] = useState([]);
useEffect(() => {
fetch('/api/tasks')
.then(res => res.json())
.then(data => setTasks(data))
.catch(err => console.error('拉取任务失败:', err));
}, []);
// ...渲染逻辑不变
}
坑来了:本地开发时,前端跑在 3000 端口,后端在 8000,跨域请求直接被浏览器拦住!
解决方法有两个:
- 后端加 CORS 头(但测试环境权限不好改)
- 利用 CRA 的 proxy 功能
我在 package.json 里加一行:
"proxy": "http://localhost:8000"
重启 dev server,搞定!现在所有 /api/xxx 的请求都会自动代理到后端。这招在联调阶段简直救命。
性能优化:别让列表卡成 PPT
随着爬虫任务越来越多,页面开始变慢。我打开 Chrome DevTools 的 Performance 面板,录制一下交互——好家伙,每次状态更新都重新渲染整个列表!
问题出在:父组件 state 变更,所有子组件都会 re-render。虽然 React 有 diff 优化,但如果子组件很多,还是有开销。
解决方案很简单:用 React.memo 包裹 TaskCard:
const TaskCard = React.memo(({ task }) => {
// ...
});
这样只有当 task 对象本身变化时,组件才会更新。配合 useCallback 或 useMemo 管理 props,性能立马提升。
另外,如果列表超长(比如上千条任务),建议用虚拟滚动(如 react-window)。不过我们目前数据量不大,先不折腾。
构建部署:别让运维再骂你
开发完当然要上线。CRA 的构建命令超简单:
npm run build
生成的 build/ 目录只有几十 KB(gzip 后),比之前的 jQuery 版本小了 90%!我把文件扔给运维,他居然回了个“👍”,这可是稀罕事。
顺便提一句:React 默认做了代码分割和懒加载,首屏加载速度飞快。我们甚至没手动优化,Lighthouse 分数就从 40+ 提到了 85+。
为什么我推荐后端同学也学点 React?
写完这个小项目,我彻底理解了为什么现代前端框架能统治江湖。它不只是“写页面”,而是一套声明式、组件化、可维护的 UI 构建哲学。
尤其对我们这种常和后端打交道的人:
- 组件化思想和微服务很像:高内聚、低耦合
- 状态管理(如 Context 或 Redux)其实和后端的“服务状态”异曲同工
- 甚至调试思路也相通:日志、断点、性能剖析
而且现在前后端边界越来越模糊。你写个爬虫,总得有个界面让人操作吧?与其求前端同事排期,不如自己撸一个。
最后的小建议
如果你也是后端出身,想试试 React,别一上来就啃 Hooks 原理或 Fiber 架构。先照着文档搭个 TodoList,再结合自己的业务场景(比如我的爬虫看板),边做边学。
记住:会用比懂原理更重要——至少在 deadline 面前是这样 😅
对了,这套代码我已经整理成开源模板,放 GitHub 上了。欢迎 star,也欢迎提 PR。毕竟技术分享的意义,不就是让别人少踩点坑嘛?
补充:常用命令速查表
| 场景 | 命令 |
|---|---|
| 创建新项目 | npx create-react-app my-app |
| 启动开发服务器 | npm start |
| 构建生产版本 | npm run build |
| 运行测试 | npm test |
| 添加 TypeScript | --template typescript |
| 代理 API 请求 | 在 package.json 中添加 "proxy": "http://localhost:8000" |
写完这篇,已经是凌晨一点。窗外陆家嘴的灯光还亮着,我关掉电脑,心想:明天演示要是顺利,是不是能申请换把人体工学椅?
毕竟,写代码的人,值得更好的椅子。

评论 0