技术文章

向量宇航员
2026-06-30 03:32
阅读 718

从DBA转后端后我在家用React Native手搓了个APP

上周五晚上,我家那只橘猫正趴在我的HHKB键盘上睡觉,我端着半杯冷掉的咖啡,盯着屏幕上终于跑通的Metro Bundler,长舒了一口气。

熟悉我的老读者都知道,我是个DBA出身的后端开发。早年跟MySQL、Oracle死磕,对数据库索引、慢查询、事务隔离级别有着近乎病态的执念。后来转做后端,依然改不了看啥都想建个表的毛病。平时写代码是个纯粹的Vim党,基本不用IDE,连同事天天吹爆的JetBrains Junie我都懒得装,觉得Vim的肌肉记忆和极客感才是王道。

本来我在家远程办公,日子过得挺滋润,每天写写Go,优化优化SQL,直到上个月产品经理老李给我挖了个坑。

老李说:“咱们内部那个任务流转系统太难用了,移动端体验极差,你抽空用React Native搞个APP呗,反正你后端接口都现成的。”

我当时就想把键盘砸他脸上。我一个写后端和搞数据库的,你让我写前端?还是跨端?但老李紧接着抛出了杀手锏:“这个算你Q3的绩效亮点,而且这周不用参加早会。”

行吧,为了不用早起,也为了绩效,我接了。其实学RN的契机早就有了,一直想给家里搞个智能中控面板,但总觉得前端水太深。这次算是被赶鸭子上架,直接实战驱动。

环境搭建:从入门到想砸电脑

RN的环境搭建,懂的都懂,简直是“从入门到放弃”的捷径。Android那边要配Java环境、Gradle,iOS那边要搞CocoaPods、Xcode。我在家折腾了整整两天,遇到了各种奇葩报错。

比如那个经典的Execution failed for task ':app:checkDebugAarMetadata',当时真的想顺着网线过去把RN的维护者打一顿。最后查了半天StackOverflow,发现是某个第三方库的依赖版本冲突,改了改build.gradle里的ext配置,顺便把minSdkVersion提了上去才搞定。iOS那边更绝,CocoaPods安装慢得像蜗牛,最后我是挂了全局代理,顺便把Podfile里的源换成了清华镜像才熬过去。

Vim党的倔强与AI降维打击

代码编辑这块,我坚决捍卫Vim的尊严。我配置了Neovim,装了coc.nvimtypescript-language-server。虽然同事小王天天在我耳边念叨:“哥,你试试JetBrains Junie吧,那AI补全,那代码重构,丝滑得很!”但我就是不听。不过说实话,写RN这种UI代码,Vim确实不如IDE直观,尤其是调Flexbox布局的时候,没有个可视化的预览,全靠脑补,调个居中能让我怀疑人生。

既然纯靠手写太痛苦,我决定引入AI来当我的“外包团队”。

首先是GPT-4,这玩意儿写React Native的样式和组件简直是神器。我只要把需求描述清楚,它生成的StyleSheet基本不用怎么改。不过它有时候会幻觉,比如给我推荐一些已经废弃的RN API,这时候就得靠我多年的后端排错直觉来甄别了。

对于代码质量,我请出了Qwen。我写了个脚本,把每天写的TS代码扔给Qwen的API做Code Review。它不仅能挑出我写的“面条代码”,还能顺便帮我优化一下TypeScript的类型定义。有次它指出我的一个闭包导致了内存泄漏,我一看,好家伙,useEffect的依赖数组漏写了,这要是上线了,APP跑半小时就得OOM。

更骚的操作是,我用CrewAI搭了个自动化生成CRUD页面的Agent。我定义了两个Agent,一个是“需求分析师”,一个是“RN开发”。我只要输入“生成一个用户管理列表页,包含搜索、分页和删除功能”,CrewAI就能自动规划任务,调用GPT-4生成对应的组件代码和Mock数据。虽然生成的代码有时候有点冗余,但作为脚手架来说,至少让我少写了三百行重复代码,让我有更多时间去死磕底层逻辑。

DBA的执念:数据层架构设计

说到这,必须聊聊我的老本行。RN应用本地肯定需要存数据,官方推荐的是AsyncStorage,但这玩意儿在数据量大或者复杂查询时就是个灾难,本质上就是个Key-Value存储。

作为DBA,我怎么可能容忍没有索引、没有事务的存储方案?我果断引入了WatermelonDB。这玩意底层是基于SQLite的,完美契合我的口味。

在设计数据模型时,我严格遵循第三范式,该建索引的地方绝不手软。比如任务表里的statuscreated_at字段,我直接加了复合索引。

// 定义Task模型,看着就像在建表
class Task extends Model {
  static table = 'tasks'
  
  // 字段定义,严谨得像DDL
  static associations = {
    [users.table]: { type: 'belongs_to', key: 'user_id' }
  }

  @text('title') title
  @text('status') status
  @date('created_at') createdAt
  
  // 查询时利用索引,拒绝全表扫描
  @children('comments') comments
}

// 查询示例,强迫症看着就是舒服
const unfinishedTasks = await database
  .get('tasks')
  .query(
    Q.where('status', 'pending'),
    Q.sortBy('created_at', Q.desc),
    Q.take(20)
  )
  .fetch();

看着这些规规矩矩的Model定义,我仿佛又回到了当年写DDL语句的岁月,心里那叫一个舒坦。前端同事看到我把本地数据库设计得这么规范,直呼内行。

踩坑与性能优化:移动端不是Web

APP写完后,真机测试阶段又给我上了一课。移动端和Web端还是有本质区别的,尤其是不同平台的适配和性能问题。

1. 键盘遮挡与刘海屏 在iOS上,输入框被键盘遮挡是家常便饭。我一开始自己算高度,搞得焦头烂额。后来老老实实引入了react-native-keyboard-aware-scroll-view,世界瞬间清静了。至于刘海屏和底部小黑条,react-native-safe-area-context是必装的,别想着自己手写paddingTop,各机型尺寸能把你逼疯。

2. 列表渲染性能 老李提了个需求,要在任务列表里展示几千条历史数据。我一开始 naive 地用了ScrollView嵌套map,结果在Android低端机上直接卡成PPT,滑动掉帧掉得亲妈都不认识。 赶紧换成FlatList,并加上getItemLayout来跳过动态高度计算,同时开启removeClippedSubviews。为了极致的性能,我还把列表项组件用React.memo包了一层,防止父组件状态更新导致的全量重渲染。这一套组合拳打下来,FPS稳在了60,老李试用的时候终于没再骂街。

3. 内存泄漏的幽灵 在页面跳转时,我发现APP的内存占用一直在涨。排查了半天,发现是定时器没清理,还有几个订阅事件在组件卸载时没取消。在RN里,组件的生命周期和Web端略有不同,一定要在useEffect的return函数里做好清理工作。

useEffect(() => {
  const timer = setInterval(() => {
    // 轮询任务状态
    fetchTaskStatus();
  }, 5000);

  const subscription = EventListener.subscribe('taskUpdate', handleUpdate);

  // 清理工作,DBA的严谨在这里体现
  return () => {
    clearInterval(timer);
    subscription.remove();
  };
}, []);

打包发布:最后一公里

代码写完了,打包上架又是另一场修行。Android那边要搞签名证书、混淆配置,还要应对各大应用市场五花八门的审核要求。我最后选择了先上蒲公英和TestFlight,让内部员工先测。

iOS打包的时候,Xcode的证书配置让我这个习惯了Linux命令行的人抓狂了好一阵。什么Provisioning Profile、App ID、Push Notification证书,搞得我头晕眼花。最后是在苹果开发者后台一顿点,加上在Fastlane里配了自动化脚本,才算把这条路跑通。

总结与心得

折腾了一个多月,这个内部APP终于上线了。虽然界面不如专业前端做的那么炫酷,但胜在流畅、稳定,尤其是数据同步那块,得益于WatermelonDB的离线优先架构,弱网环境下体验出奇的好。

回顾这次RN实战,我有几点深刻体会:

  1. 不要迷信跨端:RN确实能提高效率,但遇到深度依赖原生硬件(比如复杂的蓝牙、NFC)或者极致性能要求的场景,还是得写原生。
  2. AI是真正的生产力:GPT-4、Qwen和CrewAI这些工具,帮我跨越了前端UI编写的鸿沟,让我能把精力集中在架构和数据层上。未来不会用AI的程序员,真的会被淘汰。
  3. 后端思维在移动端同样适用:状态管理、数据流、本地缓存,这些本质上和后端的高并发、缓存、数据库设计是相通的。DBA的执念,反而成了我优化APP性能的利器。

现在,老李又来找我了:“哥,咱们那个数据大屏,能不能也用RN搞个Pad端适配?” 我看了看他,默默打开了终端,敲下了vim app.tsx。 行吧,谁让我是个热爱折腾的程序员呢。不说了,猫又把咖啡杯碰倒了,我得先去收拾一下。

评论 0

最热最新
暂无评论
向量宇航员Lv.1
0
影响力
0
文章
0
粉丝