面试 移动跨平台方案对比

756 阅读6分钟

移动跨平台方案对比:WEEX、React Native、Flutter和PWA

传统的原生Android、iOS开发面临着诸多难以解决的问题,例如开发周期长、迭代缓慢等,因此很多公司备受困扰。近年来,伴随着“大前端”概念的提出和兴起,涌现出一大批移动跨平台开发框架和模式,为解决传统移动开发问题找到了新的方向。

从早期的PhoneGap、Inoic等Hybrid混合技术,到现在耳熟能详的React Native、WEEX和Flutter等跨平台技术,借助这些优秀的跨平台开发框架,在不牺牲性能和体验的前提下,开发进度和多端研发的问题得到有效解决。

WEEX是由阿里巴巴研发的一套移动跨平台技术框架,最初是为了解决移动开发过程中频繁发版和多端研发的问题而开发的。使用WEEX提供的跨平台技术,开发者可以很方便地使用Web技术来构建具有可扩展的原生性能体验的应用,并支持在Android、iOS、YunOS和Web等多平台上部署。具体来说,当在项目中集成WeexSDK之后,就可以使用JavaScript(JS)和主流的前端框架来开发移动应用了。

WEEX的整个工作流程图如上,WEEX框架中最核心的部分是JavaScript Runtime。具体来说就是,当需要执行渲染操作时,在iOS环境下选择基于JavaScriptCore的iOS系统提供的JSContext,在Android环境下使用基于JavaScriptCore的JavaScript引擎。

当JSBundle从服务器端下载完成之后,WEEX在Android、iOS和Web端会运行一个JavaScript引擎来执行JSBundle,同时向各终端的渲染层发送渲染指令,并调度客户端的渲染引擎实现视图渲染、事件绑定和处理用户交互等操作。

React Native是Facebook公司于2015年4月开源的跨平台移动应用开发框架,它是Facebook早先开源的React框架在原生移动应用平台上的衍生产物,目前主要支持iOS和Android两大平台。

React Native使用JavaScript语言来开发移动应用,但UI渲染、网络请求等功能均由原生平台实现。具体来说就是,开发者编写的JavaScript代码会通过中间层转化为原生组件后再执行,因此熟悉Web前端开发的技术人员只需要很短的学习过程,就可以进-入移动应用开发领域,并在不牺牲用户体验的前提下提高开发效率。

作为一个跨平台技术框架,React Native从上到下可以分为JavaScript层、C++层和原生层。其中,C++层主要用于实现动态链接库(.so文件),以作为中间适配层进行桥接,并实现JavaScript端与原生平台的双向通信。

在React Native的三层架构中,最核心的就是中间的C++层,C++层最核心的功能就是封装JavaScriptCore,用于执行对JavaScript的解析。同时,原生平台提供的各种原生模块(如网络请求模块、ViewGroup组件模块)和JavaScript端提供的各种模块(如JS EventEmiter模块)都会在C++层实现的.so文件中被保存起来,最终通过C++层中保存的映射实现两端的交互。React Native框架的工作原理如下图。

React Native的开发过程中,大多数情况下开发人员并不需要了解React Native框架的具体细节,只需要专注JavaScript端的代码逻辑实现即可。但需要注意的是,由于JavaScript代码运行在独立的JavaScript线程中,所以在JavaScript中不能处理耗时的操作,如fetch网络请求、图片加载和数据持久化等。

最终,JavaScript代码会被打包成一个bundle文件并自动添加到应用程序的资源目录下,而应用程序最终加载的也是打包后的bundle文件。React Native的打包脚本位于/node_modules/react-native/local-cli目录下,打包后通过metro模块压缩成bundle文件。通常bundle文件只包含打包的JavaScript代码,并不包含图片、多媒体等静态资源,而打包后的静态资源会被复制到对应的平台资源文件夹中。

总体来说,React Native使用JavaScript来编写应用程序,然后调用原生组件执行页面渲染操作,在提高了开发效率的同时又保留了原生的用户体验。并且,伴随着Facebook重构React Native工作的完成,React Native也将变得更快、更轻量、更强大。

Flutter是谷歌公司开源的移动跨平台框架,其历史最早可以追溯到2015年的Sky项目,该项目可以同时运行在Android、iOS和Fuchsia等包含Dart虚拟机的平台上,并且性能无限接近原生平台。与React Native和WEEX使用JavaScript作为编程语言,以及使用平台自身引擎渲染界面不同,Flutter直接选择使用2D绘图引擎库Skia来渲染界面。

如上图,Flutter框架主要由Framework层和Engine层组成,我们基于Framework层开发的App最终会运行在Engine层上。其中,Engine是Flutter提供的独立虚拟机,正是由于它的存在,Flutter程序才能运行在不同的平台上,实现跨平台运行的能力。

与React Native和WEEX使用原生组件渲染界面不同,Flutter并不需要使用原生组件来渲染界面,而是使用自带的渲染引擎(Engine层)来绘制页面组件(Flutter显示单元),并且Dart代码会通过AOT被编译为对应平台的原生代码,实现与平台的直接通信,不需要通过JavaScript引擎进行桥接,也不需要使用原生平台的Dalvik虚拟机。Engine层的渲染架构图如下。

作为Flutter框架的重要组成部分,Widget是Flutter应用界面开发的基本内容,每个Widget都是界面的不可变声明。在Flutter应用开发中,Widget是不能直接更新的,需要通过Widget的状态来间接更新,这是因为Flutter的Widget借鉴了现代响应式框架的构建过程,它有自己特有的状态。当Widget的状态发生变化时,Widget会重新构建用户界面,并且Flutter会对比前后的不同,以确保底层渲染树从一个状态转换到下一个状态时所需的更改最小。

总体来说,Flutter是目前最好的跨平台解决方案之一,它只用一套代码便可生成Android和iOS两种平台上的应用,很大程度上减少了App的开发和维护成本。同时,Dart语言强大的性能表现和丰富的特性,也使得跨平台开发变得更加便利。而不足的是,Flutter还处于初期测试阶段,许多功能还不是特别完善,而全新的Dart语言也增加了开发者的学习成本。Flutter要完全替代Android和iOS原生开发,还有比较长的路要走。