移动跨平台技术方案总结
“得移动端者得天下”,移动端取代PC端,成为了互联网行业最大的流量分发入口,因此不少公司制定了“移动优先”的发展策略。
为了帮助读者更好地学习WEEX,本节将对React Native、Weex和Flutter等主流的跨平台方案进行简单的介绍和对比。
React Native
React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的React框架在原生移动应用平台的衍生产物,目前主要支持iOS和安卓两大平台。
RN使用Javascript语言来开发移动应用,但UI渲染、网络请求等均由原生端实现。具体来说,开发者编写的Javascript代码,通过中间层转化为原生控件后再执行,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域,并可以在不牺牲用户体验的前提下提高开发效率。
作为一个跨平台技术框架,RN从上到下可以分为Javascript层、C++层和Native层。其中,C++层主要用于实现动态连结库(.so),作为中间适配层桥接,实现js端与原生端的双向通信交互,如下图所示是RN在Android平台上的通信原理图。
在RN的三层架构中,最核心的就是中间的C++层,C++层最核心的功能就是封装JavaScriptCore,用于执行对js的解析。同时,原生端提供的各种Native Module(如网络请求,ViewGroup控件模块)和JS端提供的各种JS Module(如JS EventEmiter模块)都会在C++实现的so文件中保存起来,最终通过C++层中的保存的映射实现两端的交互。
在RN开发过程中,大多数情况下开发人员并不需要需要了解RN框架的具体细节,只需要专注JS端的逻辑代码实现即可。但是需要注意的是,由于js代码是运行在独立的JS线程中,所以在js中不能处理耗时的操作,如fetch、图片加载和数据持久化等操作。
最终,JS代码会被打包成一个bundle文件并自动添加到应用程序的资源目录下,而应用程序最终加载的也是打包后的bundle文件。RN的打包脚本位于“/node_modules/react-native/local-cli”目录下,打包后通过metro模块压缩成bundle文件,而bundle文件只包含打包js的代码,并不包含图片、多媒体等静态资源,而打包后的静态资源会是被拷贝到对应的平台资源文件夹中。
总的来说,RN使用Javascript来编写应用程序,然后调用原生组件执行页面渲染操作,在提高了开发效率的同时又保留了Native的用户体验。并且,伴随着Facebook重构RN工作的完成,RN也将变得更快、更轻量、性能更好。
Weex
作为一套前端跨平台技术框架,Weex建立了一套源码转换以及Native与Js通信的机制。Weex表面上是一个客户端框架,但实际上它串联起了从本地开发、云端部署到分发的整个链路。
具体来说,在开发阶段编写一个.we文件,然后使用Weex提供的weex-toolkit转换工具将.we文件转换为JS bundle,并将生成的JS bundle上传部署到云端,最后通过网络请求或预下发的方式加载至用户的移动应用客户端。当集成了Weex SDK的客户端接收到JS bundle文件后,调用本地的JavaScript引擎执行环境执行相应的JS bundle,并将执行过程中产生的各种命令发送到native端进行界面渲染、数据存储、网络通信以及用户交互响应。
由上图可知,Weex框架中最核心的部分就是JavaScript Runtime。具体来说,当需要执行渲染操作时,在iOS环境下选择基于JavaScriptCore内核的iOS系统提供的JSContext,在Android环境下使用基于JavaScriptCore内核的JavaScript引擎。
当JS bundle从服务器下载完成之后,Weex的Android、iOS和H5会运行一个JavaScript引擎来执行JS bundle,同时向各终端的渲染层发送渲染指令,并调度客户端的渲染引擎实现视图渲染、事件绑定和处理用户交互等操作。
由于Android、iOS和H5等终端最终使用的是native渲染引擎,也就是说使用同一套代码在不同终端上展示的样式是相同的,并且Weex使用native引擎渲染的是native组件,所以在性能上比传统的WebView方案要好很多。
当然,尽管Weex已经提供了开发者所需要的最常用的组件和模块,但面对丰富多样的移动应用研发需求,这些常用基础组件还是远远不能满足开发的需要,因此Weex提供了灵活自由的扩展能力,开发者可以根据自身的情况定制属于自己客户端的组件和模块,从而丰富Weex生态。
Flutter
Flutter是Google开源的移动跨平台框架,其历史最早可以追溯到2015年的Sky项目,该项目可以同时运行在Android、iOS和fuchsia等包含Dart虚拟机的平台上,并且性能无限接近原生。相较于RN和Weex使用Javascript作为编程语言与使用平台自身引擎渲染界面不同,Flutter直接选择2D绘图引擎库skia来渲染界面。
如上图所示,Flutter框架主要由Framework和Engine层组成,而我们基于Framework开发App最终会运行在Engine上。其中,Engine是Flutter提供的独立虚拟机,正是由于它的存在Flutter程序才能运行在不同的平台上,实现跨平台运行的能力。
与RN和Weex使用原生控件渲染界面不同,Flutter并不需要使用原生控件来渲染界面,而是使用Engine来绘制Widget(Flutter显示单元),并且Dart代码会通过AOT编译为平台的原生代码,实现与平台的直接通信,不需要JS引擎的桥接,也不需要原生平台的Dalvik虚拟机,如图1-5所示。
同时,Flutter的Widget采用现代响应式框架来构建,而Widget是不可变的,仅支持一帧,并且每一帧上的内容不能直接更新,需要通过Widget的状态来间接更新。在Flutter中,无状态和有状态Widget的核心特性是相同的,视图的每一帧Flutter都会重新构建,通过State对象Flutter就可以跨帧存储状态数据并恢复它。
总的来说,Flutter是目前跨平台开发中最好的方案,它以一套代码即可生成Android和iOS平台两种应用,很大程度上减少了App开发和维护的成本,同时Dart语言强大的性能表现和丰富的特性,也使得跨平台开发变得更加便利。而不足的是,Flutter还处于Alpha阶段,许多功能还不是特别完善,而全新的Dart语言也带来了学习上的成本,如果想要完全替代Android和iOS开发还有比较长的路要走。
PWA
PWA,全称Progressive Web App,是Google在2015年提出渐进式的网页技术。PWA结合了一系列的现代Web技术,并使用多种技术来增强Web App的功能,最终可以让网页应用呈现和原生应用相似的体验。
相比于传统的网页技术,渐进式Web技术是可以横跨Web技术及Native APP开发的技术解决方案,具有可靠、快速且可参与等诸多特点。
具体来说,当用户从手机主屏幕启动时,不用考虑网络的状态就可以立刻加载出PWA。并且,相比传统的网页加载速度,PWA的加载速度是非常快的,因为PWA使用了Service Worker 等先进技术。除此之外,PWA还可以被添加在用户的主屏幕上,不用从应用商店进行下载即可通过网络应用程序Manifest file提供类似于APP的使用体验。
作为一种全新Web技术方案,PWA的正常工作需要一些重要的技术组件,它们协同工作并为传统的Web应用程序注入活力,如图1-8所示。
其中,Service Worker表示离线缓存文件,其本质是Web应用程序与浏览器之间的代理服务器,可以在网络可用时作为浏览器和网络间的代理,也可以在离线或者网络极差的环境下使用离线的缓冲文件。
Manifest则是W3C一个技术规范,它定义了基于JSON的清单,为开发人员提供一个放置与Web应用程序关联的元数据的集中地点。Manifest是PWA 开发中的重要一环,它为开发人员控制应用程序提供了可能。
目前,渐进式Web应用还处于起步阶段,使用的厂商也是诸如Twitter、淘宝、微博等大平台。不过,PWA作为Google主推的一项技术标准,Edge、Safari和FireFox等主流浏览器也都开始支持渐进式Web应用。因此,可以预见的是,PWA必将成为继移动之后的又一革命性技术方案。
对比
在当前诸多的跨平台方案中,RN、Weex和Flutter无疑是最优秀的。而从不同的细节来看,三大跨平台框架又有各自的优点和缺点,可以通过表1-1来查看。
对比类型 | React Native | Weex | Flutter |
---|---|---|---|
支持平台 | Android/IOS | Android/IOS/Web | Android/IOS |
实现技术 | JavaScript | JavaScript | 原生编码/渲染 |
引擎 | JS V8 | JSCore | Flutter Engine |
编程语言 | React | Vue | Dart |
bundle包大小 | 单一、较大 | 较小、多页面 | 不需要 |
框架程度 | 较重 | 较轻 | 重 |
社区 | 活跃、FB维护 | 不活跃 | 活跃 |
如上表所示,RN、Weex采用的技术方案大体相同,它们都使用JavaScript作为编程语言,然后通过中间层转换为原生的组件后再利用Native渲染引擎执行渲染操作。而Flutter直接使用skia来渲染视图,而Flutter Widget则使用现代响应式框架来构建,和平台没有直接的关系。就目前跨平台技术来看,JavaScript在跨平台开发中可谓占据半壁江山,大有“一统天下”的趋势。
从性能方面来说,Flutter的性能理论上是最好的,RN和Weex次之,并且都好于传统的WebView方案。但从目前的实际应用来看却并没有太大的差距,特别是和0.5.0版本以上的RN对比性能体验上差异并不明显。
而从社群和社区的活跃来看,RN和Flutter无疑是最活跃的,RN经过4年多的发展已经成长为跨平台开发的实际领导者,并拥有各类丰富的第三方库和开发群体。Flutter作为最近才火起来的跨平台技术方案,不过目前还处在beta阶段,商用的实例也很少,不过应该看到google的号召力一直是很强,未来究竟如何发展让我们拭目以待。
示例
eros-yanxuan
简介
eros-yanxuan 是基于 eros 开发的Weex项目,部分页面参考了项目网易严选 weex 版本,欢迎star或fork。
运行
确保你本地已经集成了 eros 开发所需的环境。
clone 项目到本地:
$ git clone https://github.com/xiangzhihong/eros-yanxuan.git
进入目录,下载前端所需的依赖:
$ cd eros-yanxuan $ npm install
iOS SDK
打开platforms目录下的WeexEros项目,在WeexEros中使用pod添加依赖。
$ cd platforms/ios/WeexEros $ pod update // 下载 iOS 依赖 $ open WeexEros.xcworkspace // 自动打开项目
选中模拟器,点击绿色箭头运行 app 即可。
Android
对于Android工程来说,使用Android Studio打开platforms目录下的WeexFrameworkWrapper的Android工程,然后使用install.sh安装Android工程的需要依赖包nexus和wxframework。
具体可以参考自行导入项目,便可运行起来。
运行
- 项目根目录下运行
eros dev
- 关闭调试,拦截器,打开热更新
- 重新 build app
效果
Question
运行过程中出现问题在以下地址解决方法,如果没有找到,请加群:515980159