我被逼着用React Native搞了个App,结果真香了
上周五晚上十点,办公室只剩我一人。窗外北京的晚高峰早就散了,而我还在和一个诡异的白屏Bug死磕。事情起因是产品经理在周三站会上轻描淡写地说:“咱们能不能做个移动端入口?用户都在手机上刷。”——说得好听,可我们团队压根没前端人手,后端全是Java和Go老炮儿。
作为那个“懂点前端”的DevOps工程师(其实也就平时写写CI/CD脚本、调调K8s配置),我被领导点名:“你不是天天用ChatGPT写代码吗?试试React Native,跨平台,一次开发双端上线,快!”
行吧,谁让我去年靠Claude三分钟生成了个Prometheus告警规则救了双11大促呢。这次,也只能硬着头皮上了。
为啥选React Native?真不是跟风
说实话,我一开始想直接上Flutter。但转念一想:我们后端是Node.js + NestJS,前端已有React Web项目,团队里至少有两人能看懂JSX。再者,React Native的生态对爬虫数据展示特别友好——没错,这个App的核心功能之一,就是展示我们内部爬虫抓取的行业数据。
我们的爬虫系统每天从数百个网站抓取结构化数据,存入MongoDB,后端通过REST API暴露。以前这些数据只在管理后台看,现在要推到移动端给客户用。所以技术栈必须能快速对接现有API,且支持动态更新内容(毕竟爬虫数据每小时都在变)。
React Native + Axios + React Navigation,这套组合拳打下来,两天就能跑通第一个页面。
环境搭建:别信官方文档,它骗人
React Native官网说“只需一条命令”,但现实是:我在Mac上折腾了整整一天。Xcode版本不对、Android SDK路径乱、Node版本冲突……最离谱的是,npx react-native init 居然卡在 Installing CocoaPods dependencies 超过40分钟。
后来还是靠ChatGPT提醒我:加个国内镜像源!
# 终于搞定iOS依赖
cd ios && pod install --repo-update --verbose
安卓更惨。模拟器启动慢如蜗牛,真机调试又得开USB调试、允许未知来源。最后我直接用了Expo Dev Client,扫码即跑,省下半小时生命。
小贴士:如果你也在北京,通勤路上别指望用公司WiFi拉Docker镜像,更别提Android SDK。提前在家缓存好,否则地铁上只能干瞪眼。
写第一个组件:从爬虫数据到列表页
后端API很简单,GET /api/crawled-data 返回JSON数组。我用useEffect + fetch 拉数据,渲染成FlatList:
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
const DataList = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://our-backend.example.com/api/crawled-data')
.then(res => res.json())
.then(setData)
.finally(() => setLoading(false));
}, []);
if (loading) return <ActivityIndicator size="large" style={{ flex: 1 }} />;
return (
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={{ padding: 16, borderBottomWidth: 1 }}>
<Text>{item.title}</Text>
<Text style={{ color: '#666' }}>{item.source}</Text>
</View>
)}
/>
);
};
看似简单,但坑不少:
- 网络权限:安卓需要在
AndroidManifest.xml加<uses-permission android:name="android.permission.INTERNET" /> - HTTPS强制:iOS默认拒绝HTTP请求,得在
Info.plist里加例外(生产环境千万别这么干!) - 状态管理:数据一多就得上Redux Toolkit,否则组件嵌套三层就疯了
平台适配:iOS和安卓真的不一样
同一个按钮,在iOS上圆润优雅,在安卓上却像个方块。字体大小、间距、动画速度……处处是差异。
我用Platform.OS做条件渲染:
import { Platform, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
button: {
padding: 12,
borderRadius: Platform.OS === 'ios' ? 10 : 4,
// ...
}
});
但更狠的是导航栏。iOS有返回手势,安卓有物理返回键。React Navigation虽然抽象了大部分差异,但自定义头部时还是得分别处理。
另外,性能优化不能忽视。爬虫数据可能上千条,全塞进FlatList会卡死。解决方案是:
- 用
getItemLayout预计算高度 - 开启
windowSize和maxToRenderPerBatch - 图片懒加载(用
react-native-fast-image)
发布上线:比部署K8s还刺激
开发完只是开始,发布才是噩梦。苹果审核要等3天,谷歌商店要填一堆隐私政策(因为用了网络权限,被认定“收集用户数据”)。
我们后端API加了CORS,但App直连后端有风险。于是临时搭了个Nginx反向代理,把/api 转发到内网服务——这活儿本来该后端干,但他们正忙着修爬虫被封IP的Bug,只能我上。
打包命令也记一下,免得下次又查:
# Android
cd android && ./gradlew assembleRelease
# iOS(需要Xcode Archive)
npx react-native build-ios --mode "release"
最终APK只有12MB,比原生小多了。用户反馈“加载快、不卡”,虽然我知道那是因为后端缓存加了Redis,但功劳算我头上,不亏。
总结:DevOps玩RN,到底值不值?
说实话,如果只是做个展示型App,React Native真香。但如果是高性能游戏或复杂交互,还是原生稳。
对我这种DevOps来说,最大收获是打通了全链路:从爬虫 → 后端API → 移动端展示 → 应用商店分发。以前只知道K8s里Pod挂了要重启,现在知道用户点不开App也会骂娘。
而且,用ChatGPT辅助写RN代码效率极高。比如让它“生成一个带下拉刷新的FlatList组件”,秒出可用代码,我只需微调样式。
| 项目 | 耗时 | 备注 |
|---|---|---|
| 环境搭建 | 1天 | 主要卡在Xcode和Pod |
| 核心功能开发 | 2天 | 包括对接后端API |
| 适配与优化 | 1天 | 安卓/iOS样式统一 |
| 打包发布 | 1.5天 | 苹果审核占大头 |
总共5天半,从零到上线。虽然过程中有三次想砸电脑(尤其是Xcode编译失败时),但看到用户真实使用截图发到群里,那种成就感,比修好一个P0级线上事故还爽。
所以,如果你也是后端或运维,被逼着搞移动端——别慌。React Native没那么可怕,尤其当你已经有现成后端和数据源。记住:工具只是工具,解决问题才是目的。
对了,下个项目产品经理说要加推送通知……我已经在研究Firebase了。救命。

评论 0