Loading... 自从 Harmony Next(5) 在 2024 年底正式发布,包括在上周 Harmony OS 6 也开启了公测,鸿蒙的进步也在今年催生了不少的跨平台框架 虽然你可能用不上,但是还是一定要了解一下,方便以后吹 ## Flutter Flutter 相信大家已经很熟悉了,自绘和 AOT 特性带来的就是统一和性能,而代价就是包体积比较大。此外,开发过程中支持 hotreload,也非常舒服,在 2025 年,Flutter 也带来了不少的更新,例如 Platform UI 线程合并,在之前,Dart 的主线程和平台线程分别跑在单独的线程,这使得交互必须使用 Channel 来通信,而在合并之后,Dart 可以直接同步调用平台代码。不过线程合并也带来不少新的问题,例如在安卓平台调试代码时,Dart 的断点会导致安卓出现 ANR 弹窗;安卓平台启动时首帧的时间会变长;不过线程合并也带来了不少的好处,例如文本输入等会变得更贴近原生,性能也会有一定提升(Timer) 而在跨平台框架百花齐放的 2025,Flutter 的核心优势其实是 Impeller,涉及到 GPU 绘制的部分一定会有着色器编译的过程,而 Skia 需要动态编译着色器,同时 Skia 的编译和帧生成是顺序处理的,也就说 Skia 总会在编译完之后生成下一帧,如果编译速度不够快,就会出现 Jank 的情况,而 Impeller 则是这个背景的产物,Impeller 可以提前编译好应用需要的着色器 Flutter 的局限性也不少: * 文字排版能力 * 没有官方热更新 * 内存占用比较高 * PC 多窗口 ## React Native 在今年,RN 的更新也是非常巨大的,在 0.76 版本之后,RN 新架构会成为创建项目时的默认选项,在前不久发布的 0.82 中,新架构成为了唯一的选项,新架构包括以下几个部分 * TurboModules * Fabric * JSI JSI 是 JS 和 Native 的之间双向的相互封装调用,有了这一层封装层,RN 可以自由切换 JS 引擎,包括 V8,Herms 等等,同时也能够让 JS 和 Native 之间同步调用 新的 Fabric 渲染器取代了之前的 UI Manager,对齐了最新的 React 特性,例如并发渲染,Suspense 组件等等 TurboModules 是 NativeModules 的增强,支持了按需加载等等 同时 RN 也在探索 Skia 与 Web GPU,但是 RN 使用 Skia 并不是想要像 Flutter 一样变成自绘,而是给比较需要性能的地方提供补充,例如图像,视频处理等等 RN 在开发中也支持 HotRelaod,同时有优秀的热更新支持,那 RN 的局限性在哪呢? * 三方库迁移到新架构 * RN 版本升级 ## CMP CMP 在之前也有提到过,其实我更愿意把它和 Flutter 放在一起对比,因为他们都是自绘方案,CMP 有自己独特的优势,例如在安卓平台,使用系统 Skia,不仅能够得到系统优化的加持,还能减少包体积,同时在桌面平台得益于强大的 JVM,可用性也比较高,例如有原生的多窗口支持。同时 Kotlin 也是许多开发者心目中优秀的语言 当然缺点也很明显 * 鸿蒙没有官方支持,两条路线 K/N 和 K/Js 未来切换麻烦 * iOS 平台的着色器问题暂时无解,可以期待一下,Skia 新的 Graphite 后段 * 安卓和 iOS 使用不同的模式,插件维护难度大 * 没有热更新 ## Kuikly [Kuikly](https://mp.weixin.qq.com/s/56vXqvTuigT4H3OB1eD96g) Kuikly 其实也是 KMP 体系下的跨平台框架,只是在做的是时候还没有 CMP,所以 Kuikly 其实是基于早期 KMM,然后自己实现 UI 来跨平台,在使用上,Kuikly 支持自研 DSL 和 Compose DSL 两种方式开发,需要注意的是,这里的 Compose DSL 并不意味着 Kuikly 能够兼容 Compose,而是采用了和 Compose 类似的语法  从渲染原理上看,Kuikly 还是依赖了原生控件,那么和 RN 有什么区别呢?主要差别其实在控件转换上,Kuikly 的编译产物和原生一致,而 RN 需要在运行时动态的生成原生组件,那 Kuikly 如何实现 UI 一致?  其实是来自 Kuikly 自己的一层原生层,Kuikly 抽象了一层 UI 统一控件,也就是原子组件,这部分是 UI 系统中最基础的组件,例如 Text,Image,View,List 等等,Kuikly 只需要确保这一部分原子组件在不同平台上的目标一致,则由原子组件组合成的上层组件也就能保持较高的一致性  Kuikly 同时提供了大部分常用组件 同时 KuiklyBase 则可以看做是 KMP 的横向扩展,为 Kuikly 提供基建,支持了鸿蒙平台,未来也会有 Kuikly 市场,提供更多的插件(饼) Kuikly 还有一个最大的特点是动态化,但是动态化场景只支持 Kotlin/JS,在 Kuikly 内部有两类组件,可动态化类型和纯内置类型,可动态化类型部分 * 不可直接依赖平台能力 * 不可使用多线程和协程 * 不可依赖内置部分 说白了就是只能动态化 JS  所以 Kuikly 的局限性包括 * UI 还是可能不一致 * 理解难度高 * 不支持 PC ## ovCompose [ovCompose](https://mp.weixin.qq.com/s/GTkzHTvWIdDmxtlRVpNgfw) 前面提到的 Kuikly 是基于 KMP 实现的,而新的 ovCompose 则是正统的基于 CMP 实现的方案,所以 ovCompose 也依赖了 KuiklyBase 作为 KMP 的扩展实现,所以主要区别在上层渲染 * Kuikly 支持两种模式,动态(Kotlin/JS),静态(Kotlin/Native)两种渲染模式,依赖原生控件,通过原子组件实现 UI 统一 * ovCompose 采用官方标准 CMP API ,Skia 自绘,支持 Android 、iOS 和鸿蒙三端,只使用 Kotlin/Native,可以看作是支持鸿蒙的 CMP  在 KMP 角度看,和 iOS 其实非常像 kotlin 1.9 使用的LLVM 11,kotlin 2.1升级到LLVM 16,但是鸿蒙平台能够支持的版本在LLVM 12 \~ 15,苹果和鸿蒙都是基于公共版本的LLVM进行修改,增加了自己的特性优化,苹果相对好的点在于公共版本的LLVM中包含有苹果的target,所以鸿蒙版本的LLVM既可以支持iOS,又可以支持鸿蒙平台 在第一步Kotlin IR转LLVM IR时采用苹果的LLVM 11,在LLVM IR生成可执行文件时使用鸿蒙的LLVM 12,这样既可以满足诉求,Kotlin本身也无需进行架构调整  <div class="tip inlineBlock share simple"> 想编译鸿蒙?先买个 Mac </div> Kuikly 和 ovCompose 是跨平台的两个方向 ● 原生渲染方案 KuiklyUI:侧重于静态化+动态化双运行模式,采用轻量原生渲染保持原生UI体验并具备高度一致性,并基于原生组件映射的方式支持Compose API,支持H5和小程序 ● 自渲染方案 ovCompose:专注于全面对齐 Compose Multiplatform 标准API,采用自渲染方式实现鸿蒙平台的适配,确保三端高度一致性。针对 iOS 上较多的存量业务,提出了多模态渲染方案解决低端iPhone内存紧张、混排原生视图、手势等问题 ## Lynx 前面的 Kuikly 和 ovCompose 更适合客户端开发者使用,那么 Lynx 则是完全为 Web 开发者设计的,目前 Lynx 的开源版本是使用 React 的 ReactLynx,当然官方也表示不只局限于 React,未来也可能有 VueLynx 等等,在目前开源的 ReactLynx 中,其实和 RN 的原理非常像,但是官方也提到,Lynx 从 [Chromium](https://www.chromium.org/chromium-projects/)、[Flutter](https://github.com/flutter) 和 [React Native](https://github.com/facebook/react-native) 等一系列项目中汲取灵感,具备快速适配一个新平台的灵活性,并且灵活到可以切换至*自渲染*,从而在任何具有图形接口的平台上实现像素级一致的渲染效果 也就是说 Lynx 可能会支持类似 Flutter 的自绘制模式,但至少现在没看到 Lynx 最具代表性的架构决策之一是**静态强制划分**用户脚本的运行环境,将用户脚本拆分跑在了两个独立的运行时上:一个[主线程](https://lynxjs.org/next/zh/guide/spec.html#main-thread-or-lynx-main-thread)运行时,它由 [**PrimJS**](https://github.com/lynx-family/primjs) 这个专为 Lynx 优化的 JavaScript 引擎驱动,有着独享的同步 UI 操作权限,用于处理初始启动和高优事件处理等任务;另一个则是[后台](https://lynxjs.org/next/zh/guide/spec.html#background-thread-aka-off-main-thread)运行时,作为用户代码的默认执行环境,以确保主线程的低负载和*非阻塞*。这一架构带来了 Lynx 的两大杀手锏: 1. [*首帧直出 (Instant First-Frame Rendering,IFR)*](https://lynxjs.org/next/zh/guide/interaction/ifr.html):[用研表明](https://www.nngroup.com/articles/response-times-3-important-limits/):如果渲染足够快(而 Lynx 正是如此),那么在界面过渡时就无需多余的反馈。Lynx 通过短暂阻塞主线程,确保首帧一次性完整呈现,因为用户不会看到空白,可以给用户带来一种即刻响应的感知体验 2. [*主线程脚本 (Main Thread Script,MTS)*](https://lynxjs.org/next/zh/react/main-thread-script.html):它是一小段静态调度的代码,被授予在主线程运行的权力,用于处理高优的事件和手势行为,非常适合那些要求极致跟手、快速响应的场景,以实现原生交互触感 这个思路类似 reactnative-reanimated 内部不好说,现在的开源版本,就是一个字节优化版 RN ## Uniapp-X 不好评价,快速过一下,就是把 uts 代码编译为原生代码 从这点看,uni-app x 是一个类 RN 的编译时框架,所以它的优势在于编译器转译得到原生性能,但是它的劣势也是在于转译 * 不同平台转译成本高,API 必然需要为了转译器而做删减 * 生态支持割裂,uni-app 和 uni-app x 插件并不通用 * 文档一坨 moveable view,rich text  666 ## 总结 | 框架 | 语言 | 渲染方式 | 特点 | 缺点 | 支持平台 | 维护企业 | | ----------------- | ------ | ------------------- | ------------------------------------------------------------------------ | --------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------- | | Flutter | Dart | 自绘 | 自绘,多平台统一, dart 和平台语言直接交互,Impeller | 占用内存大,文本场景略弱,Impeller 还需要继续打磨 | android、iOS、Web、Windows、macOS、Linux、鸿蒙(华为社区提供) | Google | | React Native | JS | 原生, Skia/WebGPU | 新架构提供性能优化,对齐 Web,引入 skia 和 webGPU 补充,code-push 热更新 | UI 一致性和新旧架构的第三方支持 | android、iOS、鸿蒙(华为社区提供),额外京东 Taro 支持小程序,web、windows、macOS、Linux 第三方支持 | Facebook | | CMP | Kotlin | 自绘 | Kotlin 体系,skia 自绘,多平台统一,支持 kn、kjs、kwasm 、kjvm 多种模式 | KN JVM、JS、Wasm 生态需要整合,没有着色器预编方案 | android、iOS、Web、Windows、macOS、Linux | Jetbrains | | Kuikly,ovCompose | Kotlin | 原生 | 基于 KMP 的类 RN 方案,在动态化有优势 | 小部分 UI 一致性场景,UI 与 CMP 脱轨 | android、iOS、Web、鸿蒙、小程序 | 腾讯 | | Lynx | JS | 原生,画饼自绘 | 对齐 Web 开发首选,秒开优化,规划丰富 | 非常早期 ,生态发展中,客户端不友好 | android、iOS、Web、Windows、macOS、鸿蒙、小程序 | 字节 | | uni-app x | uts | 原生 | 支持混写 uts 和原生代码,直接翻译为原生 | 生态插件割裂,UI 一致性问题,翻译 API 长期兼容成本 | android、iOS、Web、鸿蒙、小程序 | DCloud | © 允许规范转载 打赏 赞赏作者 微信 赞