基于前端领域移动端跨平台方案的研究

作者: 岳奎

基于前端领域移动端跨平台方案的研究0

摘要:随着互联网产品逐渐兴起,越来越多产品体验从线下搬到了线上,尤其是移动互联网产品相关,所以很多企业就会更加重视降本增效,以最快的速度推出质量满意度高、用户体验性好的产品,那么就顺势催生了很多跨端跨平台方案。文章通过分析研究对比目前主流的跨端跨平台移动端方案各自的优缺点,从各个维度给出基于原理事实的分析研究报告,得出一些针对各个方案的最佳场景案例。

关键词:移动互联网;跨端跨平台;Weex; React-Native;Flutter

中图分类号:TP311      文献标识码:A

文章编号:1009-3044(2022)20-0065-02

最早的跨端跨平台解决方案要追溯到PhoneGap的时代,也叫作Hybird时代,代表作Cordova,同时期后来也有了基于AngularJS和Cordova的增强版Ionic,这些方案都是混合开发方案。接着迎来了借助原生渲染的方案,先后出现的有React Native、Weex、uni-app等。之后出现了放弃原生渲染,自建渲染方案的自渲染技术Flutter。本文主要研究跨端方案的演进过程以及各种跨端方案的各自特性。

1 混合开发时代

混合(hybird) 开发时代的代表作有Apache Cordova[1],其前身就是PhoneGap。它允许开发者用标准的Web技术也就是HTTML5、CSS3和JavaScript来做跨平台开发。应用在每个平台的具体执行细节都被封装了,并借助封装过原生标准的API去访问每个设备的功能,比如相机拍照、地理位置定位、传感器等。

1.1 混合开发Apache Cordova实现原理以及特点

1.1.1 实现原理

因为是基于Web技术,所以必然依赖于WebView才能进行页面渲染展示。那么对于Android来讲就是利用WebView技术,对于iOS来说就是利用的UIWebView或者WKWebView。所以Web和客户端Native的通信方式是依赖于WebView提供的相关接口实现的,对于Android来讲一般常用的相互通信方式是WebView实例加载Web的URL以及Native注入全局变量(使用addJavascriptInterface[2]) 到WebView中,这样HTML5就可以全局可见地调用该方法。对于iOS来说是利用WKWebview里的evaluateJavaScript方法直接执行即可,那么H5调用Native的能力是依靠NA自身的JavaScriptCore提供接口出去供H5来调用。本质上两端通信还有一个共同的方式就是NA拦截Web的URL(也叫作标准协议规范schema) 做对应的处理,这是一个比较常用,而且容易自定义的协议规范,实现也相对简单灵活。

1.1.2 混合开发特性

开发效率方面,对前端开发者友好,前端众多生态都可以拿来使用,比传统的Android和iOS开发效率快很多,但涉及Native的部分,依然需要去熟悉掌握原理。其次是能力受限于桥接层,扩展性低。调试和错误日志不友好。热更能力方面,因为使用JS,所以是支持热更。多端一致性方面,因完全依赖于Native的webview层的内核渲染,无法媲美原生体验,涉及宿主问题必然需要开发者自己处理。性能方面,因渲染依赖于WebView,所以性能不如Native直接渲染,特别对于长列表渲染[4],性能很差。

综上所述其实Hybird方案是一个矛盾结合体,既要快,又要性能还要完善的生态。当然开发者们都看到了此缺陷所以才有了后来大家耳熟能详的React-Native。

2 原生Native渲染时代

常见的通过Native渲染的技术目前有React Native、Weex、uni-app,接下来逐个分析相关方案的原理和特性。

2.1 React Native

架构理念是Learn once,write anywhere也就是说掌握了React开发,可以同时掌握Web和App两种开发技能。React Native[3]用了react的设计模式,但UI渲染、动画效果、网络请求等功能均由原生实现。开发者编写的js代码,通过React Native的中间层转化为原生控件来渲染和响应事件,相比ionic等跨平台应用,极大地提高了用户体验。

2.1.1 React Native的框架组成、渲染原理、平台通信

首先React Native框架内部已提供了很多内置组件,如View、Text等基础布局组件,一些功能组件如Button、Picker等,用于列表展示的List组件和对应Android平台和iOS平台特有的组件、API等。同时也提供了编写与原生平台交互的接口。渲染这块主要还是把React写好的JSX代码通过ReactElements转换,然后经历React的部分生命周期再由AppRegistry.registerComponent[3]进行注册,接着通过遍历dom进行diff算法,但这里是要经过消息队列异步传递的,最终把增量的变化传递到Native侧,然后进行渲染真正的Native组件。平台通信这块主要是通过Bridge来进行通信,所有JS代码都是要经过JavaScriptCore编译,然后给到由C/C++编写的Bridge桥,当作中间人进行交换通信,再分发给对应的Android或者iOS宿主。所以这个过程中最消耗性能的其实就是渲染时的消息队列通信相关的增量变化。大致的架构图如图1所示。

2.1.2 React Native特点总结

开发效率方面,在Web基础上引进了React能力,符合前端大趋势,但涉及与Native交互的地方就需要开发者自己处理,这点还是需要对NA比较熟悉,因本地支持热加载,也有对应配套的调试dom节点元素的工具提供,开发体验是友好的。动态化方面,因为用的是react,故可以做线上热更操作,不过需要结合三方npm包或者自研NA相关的JS Bundle文件下载、上传、替换等功能。多端一致性方面,因为是渲染的NA组件,所以可以保证和Native拥有一样的用户体验,但三方组件依赖性较强,比如版本更新不及时,社区活跃度不高。性能方面,稍差于Native,但远好于Hybird,但因为渲染时需要JavaScript和原生之间不停地进行数据通信,在有些场景如拖动可能会因为通信频繁导致卡顿。其次是因为JavaScript为脚本语言,执行时需要JIT,执行效率相比AOT代码[5]仍有一定的差距。

2.2 Weex

Weex也是借助NA来做渲染的一个移动端跨平台方案。它和React Native很多方面都很相似,但还是有不同点,比如它使用的是Vuejs和Rax这两个任意一个框架来编写代码,同时Weex的渲染引擎和DSL语法层是分开的,这点和React Native理念完全不同。因为很多都和React Native相似,所以这里就简单阐述。

2.2.1 Weex整体工作流程

首先会把用vue写的项目打包成一份JS Bundle,然后部署到服务器,客户端打开某一个网页,先下载服务端的JS Bundle,然后在客户端本地执行该JS Bundle。一般会用到JavaScriptCore或者V8引擎去执行JS Bundle,JS执行引擎和浏览器执行过程类似,JS Bundle的代码被执行,生成VNode树进行patch,找到最小DOM节点的操作变化,把DOM节点的操作转变为Native DOM API的操作,然后调用WXBridge[6]进行通信,WXBridge将渲染指令分发到Native渲染引擎,由Native渲染引擎完成最终的页面渲染。

2.2.2 Weex的特性

开发效率方面,和React Native几乎没啥差别,不过本地开发调试方面没有React Native体验好。动态化方面,天然支持动态化而且还支持拆bundle,React Native当然也支持拆包但需要改造。

2.3 总结

尽管借助NA渲染方式相比混合开发性能高很多,而且方案也很完美,但还有很多不足的地方比如框架自身维护成本高,主要是因为提供的组件大多依赖原生控件,那么这些Android和iOS控件也不是一成不变的,系统厂商也会做一些迭代,那么就必然要适配,适配成本很高。所以就会存在天然抹不平双端的差异,所以才有了后来的自渲染技术。

3 自渲染技术

含义是通过框架自身的自绘引擎,来实现布局和绘制到终端,可以认为是从另一个角度的创新,为人们打开的新的方向和思考,自渲染的代表作就是Flutter,接下来我们就一起了解下Flutter的核心架构思想以及特性。

3.1 Flutter架构组成

Flutter是以Dart语言编写[6],基于Dart编写提供了很多组件也叫Widget,有两套风格的Widget,分别Material和cupertino。两套风格有很多widget,比如Text、Input等,也提供了动画、手势等通用的Widget。因为没有采用WebView,也就没有JS和Native的通信了,而是自行实现一套UI框架,在引擎底层通过Skia[6]渲染到屏幕。对于UI之外所需要使用的移动设备自身提供的服务,比如相机拍照、定位等,则采用Platform Channels[6]接口跟原生系统通信的方式来实现。

3.2 Flutter的特点

效率方面,因为采用dart语言编写,需要先熟悉dart语言,但熟练后效率有明显提升,同样也支持热Hot Reload能够很好地在本地进行快速的开发和调试。动态化方面,目前iOS是不允许进行热更的,因为苹果官方禁止JS Path,当然Android是可以热更,但大环境目前是不太友好的。平台一致性方面,可以做到像素级UI控制,能做到最大限度的还原,保证最大限度在不同平台的体验一致性,目前还支持PC、嵌入式等。性能方面,这块优于以上介绍的所有跨平台框架方案,也是最能媲美原生性能的跨平台技术方案,因为Dart代码执行效率比JS高很多,而且是通过AOT编译成平台原生代码[7],渲染采用Skia方案,既不需要JS Bridge也不涉及虚拟机[8]。

4 总结

通过从最早的Apache Cordova混合开发技术的背景开始,分析了当时混合开发时代的优劣势,当时的开发者为此做了很多努力和改进,让我们知道当时的技术方案是可以降本增效的,但有诸多弊端,于是就迎来了原生渲染技术的时代,这个时代放大了前端生态的繁荣,很多方案都是借助前端技术栈作为入口,撬动了整个跨端方案,无论是从体验、性能、一致性上都完胜混合开发,但还是有诸多不完美,比如依赖三方组件,依赖厂商适配,同步迭代更新成本高等问题。最后出现了自渲染技术,这对于整个跨平台方案来说立意高,创新强,一出来就在用户体验层面和平台一致性上完胜依赖原生Native渲染方案,但不支持热更,有一定的学习成本。所以综上所述,目前性能最佳、一致性最好的方案是自渲染。但如果想支持热更最佳选择就是React Native。

参考文献:

[1] 王亚飞,王洪飞.Apache Cordova移动应用开发实战[M].北京:清华大学出版社,2017.

[2] 张静,薛茹.基于JSBridge技术的跨平台移动应用开发研究[J].信息与电脑(理论版),2021,33(6):100-102.

[3] Eisenman B.React Native开发指南[M].黄为伟,译.北京:人民邮电出版社,2016.

[4] 向治洪.React Native移动开发实战[M].北京:人民邮电出版社,2020.

[5] 邱鹏源.React Native 精解与实战[M].北京:机械工业出版社,2018.

[6] 呙森林,张玺.Weex跨平台开发方案研究与应用[J].信息通信,2017,30(4):112-113.

[7] 舒红梅,符清芳,张艳.Flutter框架在前端开发中的应用探析[J].软件,2022,43(3):55-58.

[8] 周勇,程子清.Flutter的原理深度剖析[J].电脑编程技巧与维护,2018(11):19-21.

【通联编辑:光文玲】

经典小说推荐

杂志订阅