“再见了,React Native”是一个醒目的判断,但仅凭标题与摘要,我们无法得知它对应的是具体项目复盘、生态变化,还是技术选型调整。对开发团队更有价值的问题不是“React Native 还行不行”,而是:现有项目的问题究竟来自框架、工程治理,还是已经变化的业务目标?
离开一个跨端框架并不等于删除依赖、重写页面。它会同时影响发布流程、原生能力、人员结构、测试体系和长期维护成本。因此,真正动手之前,最好先把决策拆成可验证的工程问题。
不要把所有问题都归咎于框架
React Native 项目常见的痛点大致分为三类,而它们需要完全不同的解决办法。
运行时与平台能力问题
如果应用高度依赖相机、音视频、蓝牙、后台任务、复杂动画或系统级组件,团队通常需要维护更多原生模块。此时,跨端层节省的页面开发成本,可能会被桥接、调试和双平台适配抵消。
这类问题适合用数据判断:
- 崩溃是否集中在原生模块或跨语言边界?
- 启动时间、内存和掉帧是否已经影响核心业务?
- iOS 与 Android 是否经常需要两套不同实现?
- 框架升级是否长期被关键依赖阻塞?
工程治理问题
依赖失控、测试不足、页面边界混乱和升级困难,并不是 React Native 独有的问题。直接改写成 Swift、Kotlin 或另一套跨端框架,可能只是把旧债搬到新仓库。
如果问题主要来自构建时间、依赖版本或模块耦合,应该先尝试:锁定依赖版本、删除无人维护的包、拆分业务模块、补充端到端测试,以及明确 JavaScript 与原生代码的职责边界。
组织与业务问题
技术栈的价值还取决于团队。一个拥有成熟 iOS、Android 团队的公司,与一个主要由 Web 工程师组成的小团队,得到的答案不会相同。低频更新的内容型应用和追求极致交互的实时产品,也不应采用同一套评估标准。
因此,“是否告别”必须落到业务指标上:交付速度、线上稳定性、关键体验、招聘难度和未来两三年的维护预算。
先做一次可重复的依赖盘点
迁移计划的第一步不是创建新项目,而是弄清当前应用依赖了什么。下面的脚本可以放在 React Native 项目根目录运行。它读取 package.json,扫描 src 目录中的导入语句,并标记名称可能涉及原生能力的依赖。
这是一个启发式审计工具,不会替代人工检查;运行前可以按项目情况修改 NATIVE_HINTS。
#!/usr/bin/env python3
import json
import re
from pathlib import Path
NATIVE_HINTS = (
"react-native-",
"camera",
"bluetooth",
"firebase",
"maps",
"navigation",
"permissions",
"reanimated",
"video",
)
root = Path.cwd()
package_file = root / "package.json"
src_dir = root / "src"
if not package_file.exists():
raise SystemExit("package.json not found; run this script from the project root")
package = json.loads(package_file.read_text(encoding="utf-8"))
dependencies = {
**package.get("dependencies", {}),
**package.get("devDependencies", {}),
}
import_pattern = re.compile(
r"(?:from\s+|require\()['\"]([^'\"]+)['\"]"
)
used_packages = set()
if src_dir.exists():
for path in src_dir.rglob("*"):
if path.suffix not in {".js", ".jsx", ".ts", ".tsx"}:
continue
text = path.read_text(encoding="utf-8", errors="ignore")
for match in import_pattern.finditer(text):
name = match.group(1)
if name.startswith("."):
continue
package_name = "/".join(name.split("/")[:2]) if name.startswith("@") else name.split("/")[0]
used_packages.add(package_name)
print("dependency,version,used_in_src,native_risk")
for name, version in sorted(dependencies.items()):
used = "yes" if name in used_packages else "no"
native_risk = "review" if any(hint in name.lower() for hint in NATIVE_HINTS) else "low"
print(f"{name},{version},{used},{native_risk}")
保存为 audit_rn.py 后执行:
python3 audit_rn.py > rn-dependencies.csv
接下来不要只看依赖数量。应为每个 review 项补充四列:业务用途、维护状态、原生替代方案、迁移负责人。真正决定迁移难度的,通常是支付、推送、登录、埋点、地图和音视频等关键链路,而不是普通 UI 组件。
用“绞杀者模式”替代一次性重写
如果评估后确认需要迁移,更稳妥的方式是逐步替换,而不是冻结业务半年后整体上线。
可以把应用划分为以下边界:
| 模块 | 建议处理方式 | 验证指标 |
|---|---|---|
| 登录、支付、推送 | 先定义稳定接口,再替换实现 | 成功率、崩溃率 |
| 内容列表、设置页 | 适合作为首批迁移页面 | 开发周期、包体变化 |
| 相机、音视频、地图 | 单独制作技术原型 | 延迟、内存、耗电 |
| 核心交易流程 | 等基础设施稳定后迁移 | 转化率、错误率 |
迁移期间需要明确新旧页面之间的数据契约。例如,不要让两端直接共享不断变化的内部对象,而应约定版本化的 JSON 结构:
{
"schemaVersion": 1,
"route": "order/detail",
"params": {
"orderId": "A1024"
},
"session": {
"accessToken": "replace-at-runtime"
}
}
实际项目中不要把令牌写入日志或持久化到不安全的位置。这个结构的重点是让导航、身份和业务参数形成显式契约,使 React Native 页面与新页面可以在一段时间内共存。
选择替代方案时,比较的是约束而不是语法
迁移到原生开发通常能获得最直接的平台能力和调试体验,但需要维护两套 UI 与更多平台专属代码。迁移到另一种跨端方案可能保留单一代码库,却仍然需要面对插件质量、平台差异和框架升级。
也可以只迁移最重的平台功能,继续保留适合跨端实现的普通页面。混合架构并不天然糟糕,真正危险的是没有边界:同一业务状态被多套运行时管理、导航协议没有版本、构建流程无人负责。
动手前的决策清单
在正式说“再见”之前,团队至少应该回答这些问题:
- 有连续数周的性能、崩溃和交付效率数据吗?
- 能否证明主要瓶颈来自 React Native,而不是项目治理?
- 哪些原生模块没有可靠替代方案?
- 新架构能否灰度发布并快速回滚?
- 迁移期间谁维护旧版本,谁负责新基础设施?
- 是否计算了双栈并行、测试重建和人员培训成本?
框架迁移不是技术态度的表达,而是一项投资决策。最好的“告别”不是彻底重写得最快,而是在每一步都能发布、测量和回滚,并确保用户几乎感觉不到架构正在变化。