大家好,我是老刘
最近不少同学在问我:新出了一个很厉害的跨平台框架Perry,它能不能取代Flutter?
先说结论:从技术潜力看,Perry很值得关注;但从工程落地看,它短期内还很难取代Flutter。真正决定胜负的,不只是架构先进,而是性能、生态、可预期性三件事能不能同时成立。
接下来我们从跨平台技术的三种路线开始,看看Perry的解决方案到底有啥优缺点?
跨平台的三种技术路线
我们先把跨平台方案分成三类,这样看Perry的位置会更清楚。
1. 中间层方案
代表是React Native。业务逻辑通过中间层转换为原生组件,并交由系统原生SDK渲染。这种方案灵活省事,能很好地兼容系统差异。但缺点是存在性能损耗,主要源于中间层自身的运行消耗,以及跨语言运行时上下层通信带来的延迟(在拖拽等频繁交互场景下容易卡顿)。

2. 自带绘制引擎方案
代表是Flutter、Compose。这类方案绕过原生系统SDK,利用自带的渲染引擎直接进行UI绘制。其最大的优势是去除了中间层损耗,能实现媲美原生的性能。但代价是引擎开发维护成本高,且无法直接调用系统底层功能(如摄像头),需通过通道机制通信,在处理大数据量时仍会有性能折损。

3. 转译方案
代表是Skip。核心逻辑是通过工具将一套代码直接翻译成不同平台的原生代码。其优势在于性能无缺、功能完备。但目前主要面临三大挑战:编程语言层面的逻辑映射困难、平台间SDK框架的对应困难,以及第三方库的跨端管理问题。

有人说Perry是转译类方案,因为它把TS代码编译成原生机器代码,那真的是这样吗?我们先来看看Perry的技术方案。
Perry是什么
Perry是一套把TypeScript编译为原生应用的跨平台技术栈。你仍然可以用TS写业务和声明式UI,但最终产物不是WebView页面,而是面向目标平台的原生二进制和原生控件应用。

它的目标很明确:尽量保留前端开发体验,同时把性能、包体和系统能力拉回到原生应用级别。
官方文档可以参考:https://docs.perryts.com/
Perry的技术方案
下面我用一个Android应用来解释Perry的大致链路。
开发流程

-
代码输入
开发者编写
app.ts,包含业务逻辑和perry/ui声明式UI。 -
前端编译
Perry通过SWC工具解析TS,生成内部中间表示数据HIR,再做闭包转换、async lowering等transform。
-
原生代码生成
通过LLVM把HIR编译为目标架构机器码,而不是JS字节码。
-
运行时与绑定链接
链接Perry runtime、stdlib和native bindings,产物里包含Android侧桥接能力(JNI)。
-
UI映射到原生控件
Text、Button、VStack等组件映射到TextView、Button、LinearLayout等Android控件。 -
生成应用结构
除原生库外,还要生成
AndroidManifest、resources、主题等必要结构;splash可由package.json配置驱动。 -
打包产物
最终打包为APK,例如:
bash
perry app.ts -o app --target android
运行流程
用户启动App后,APK内由Perry生成的so库被加载,runtime初始化,应用进入Application/Activity生命周期,然后执行Perry入口逻辑。
**渲染链路是:**你写的UI组件交给Perry runtime,然后runtime通过JNI调用Android View API创建和更新原生控件。
**交互链路是:**原生点击或者触摸事件先发送给原生组件,然后经Java/Kotlin和native之间的JNI桥进入runtime,再触发你注册的事件处理代码。
性能风险
从前面的运行流程可以看出来,Perry在Android上通过JNI连接原生View与runtime,真正控制UI的是runtime,这在高频交互场景里会有额外开销。
举个典型场景:假设功能是拖拽组件时组件的位置和样式会随着位置变化,那么每一帧都可能触发位置和样式变化。
每一帧的更新通常涉及两段链路:
- 原生move事件通过JNI进入runtime。
- runtime调用你的处理代码后再通过JNI把新UI状态下发到View层。
JNI单次调用通常不是瓶颈,真正的问题是高频跨层调用叠加UI重算后,对主线程负载的压力。
所以Perry不是没有中间层成本,而是把这部分成本压到了更低水平。相比传统中间层方案,它更轻、更快,但并非零损耗。
Perry仍是中间层方案
很多同学会被编译到原生这个表述误导,以为它已经是纯转译路线。
判断标准其实很简单:运行时是否仍依赖统一调度中枢来连接业务代码与原生能力。
只要UI更新、事件回调还要经过runtime再到平台层,它就是中间层架构。
Perry与纯编译期转译方案的差异在于:
纯转译追求编译后尽量直接执行,不依赖额外的统一运行时;Perry当前仍保留runtime负责状态、事件、UI协同,这换来更统一的开发体验,也保留了跨层通信成本。
更准确的说法是:Perry不是摆脱中间层,而是把中间层做薄了。
Perry的竞争力在哪
Perry最有价值的点,是把传统中间层里最重的部分做了重构。
- 运行时执行形态更靠近原生机器码,不再依赖JS解释执行路径。
- 跨层通信路径从跨虚拟机模型收敛到JNI桥接。
- 理论上能在包体、启动、交互延迟上拿到更好的工程表现。
这也是它相比RN类方案最核心的性能竞争力来源。
这里要单独提一下热更新的问题。Perry属于中间层框架,但是并没有RN那样天然支持动态化的优势。
核心原因还在于打包的产物是编译成机器码的二进制。
而手机端操作系统比如Android、iOS对可执行的二进制文件有严格的签名校验和执行保护。
这是在安全性和用户体验上的一种权衡。
因此目前Perry只在桌面端支持热更新。
Perry能取代Flutter吗
我的判断是:短期不能,长期要看生态。
性能层面,Perry已经把中间层损耗压得很低,在大多数业务场景可能足够好。
也就是说大多数场景下用户体验和Flutter差不多。
但Flutter属于独立渲染路线,架构上天然少一层运行时到平台控件的映射负担,在复杂交互的极端场景下,性能上限仍有优势。
真正决定Perry能否挑战Flutter的关键,不在跑分,而在生态可用性。这个生态问题分两层。
一、不依赖底层系统能力的库
这部分Perry有先天优势,因为可以复用前端生态。
但根据文档,Perry是TypeScript的实用子集,不是完整兼容,这意味着部分TS/JS库可能无法直接使用。
这种不确定性在工程上是很危险的。
因为你在选型阶段很难100%确认关键依赖是否可用,一旦在开发的中途发现核心库不兼容,项目周期和架构都可能被动重排。
二、依赖底层系统能力的库
这部分是更现实的难点,比如定位、传感器(比如电池状态)、支付等。
Flutter经过多年积累,常见能力基本都有成熟插件与社区验证。也就是说你可以完全只写dart代码,需要依赖手机系统的功能都可以通过插件实现dart调用。
而Perry还在早期,原生桥接与插件生态的厚度明显不足。
如果大量能力都要团队自己补桥接,交付风险会迅速放大。
总结
如果只看技术架构,Perry是我目前看到最精彩的中间层跨平台方案之一。
它证明了一件事:中间层不一定慢,也可以做得非常接近原生体验。
但要追上Flutter,决定因素不是架构,而是生态完备度。
所以现阶段更务实的判断是:Perry值得长期跟踪,距离全面替代Flutter还需要时间。
🤝 如果看到这里的同学对客户端或者Flutter开发感兴趣,欢迎联系老刘,我们互相学习。
🎁 私信免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。可以作为Flutter学习的知识地图。
💬 : laoliu_dev
📂 老刘也把自己历史文章整理在GitHub仓库里,方便大家查阅。