flutter实践 - 跨平台的发展

背景

随着移动端从诞生到遍地开发再到平台化的收敛,为了不断满足企业对于开发效率及跨平台的一致性的追求,各种跨平台方案层出不穷。对于我们做产品设计和开发,开发效率和使用体验可以说是至关重要的两个因素。如果你身处大前端,你就不得不拥抱跨端,这是一个不以人意志为转移的趋势。从本质上来讲,跨平台开发是为了增加业务代码的复用率,减少因为要满足多个平台的适配开发而带来的开发和维护成本,从而有效降低开发成本。

方案演进

无论大大小小的跨平台方案,按照其核心的设计思想,可以划分了三个阶段

  • Web 容器
    基于设备系统原生的浏览器组件来实现页面及业务功能。代表方案有:cordova等
  • 泛Web容器
    采用web标准进行开发,在运行时由原生系统负责渲染绘制。代表方案有:RN、Weex等
  • 自渲染引擎
    自带渲染引擎,客户端仅需要提供画布便可以实现业务功能到UI的多端一致的渲染体验。代表方案:Flutter

下面我们逐个分析这三个阶段不同的设计思想与各自的优势

Web容器

Web 容器的方案,是最简单也最易操作的方案,主要采用原生系统内嵌的浏览器控件(Android的WebView,iOS的WKWebView)的方式渲染H5页面。客户端与HT定义好交互的协议,将一些原生系统能力暴露给H5通过js来调起,也就是大家说的 JSBridge。
web容器的交互设计可以通过下图来直观提现


web容器.png

这种方案最终的渲染方还是浏览器,一个H5页面呈现出来是要经过较为复杂的过程,我们可以陈列下最基础的加载过程,就可以知道这个过程的复杂性。

  1. 浏览器控件加载 HTML5 页面的 HTML 主文档。
  2. 加载过程中遇到外部 CSS 文件,浏览器另外发出一个请求,来获取 CSS 文件。
  3. 遇到图片资源,浏览器也会另外发出一个请求,来获取图片资源。这是异步请求,并不会影响 HTML 文档的加载。
  4. 加载过程中遇到 JavaScript 文件,由于 JavaScript 代码可能会修改 DOM 树,因此 HTML 文档会挂起渲染(加载解析渲染同步)的线程,直到 JavaScript 文件加载解析并执行完毕,才可以恢复 HTML 文档的渲染线程。
  5. JavaScript 代码中有用到 CSS 文件中的属性样式,于是阻塞,等待 CSS 加载完毕才能恢复执行。

从这个过程我们可以看出,一个完成的H5页面的呈现要经过浏览器控件的加载、解析和渲染三大过程,性能消耗和呈现效率相比原生页面都有很大的负面增加。虽然Web容器方案开发体验友好,跨平台兼容性强等优势,但需要承载大量的与Web指定的协议标准,会导致容器过于笨重,而且较难实现复杂交互和呈现较好的用户体验

泛Web容器

泛Web容器的方案优化了Web容器方案的浏览器加载、解析和渲染这三大过程,把影响它们独立运行的 Web 标准进行了裁剪,以相对简单的方式支持了构建移动端页面必要的 Web 标准(如 Flexbox 等),也保证了便捷的前端开发体验;同时,这个时代的解决方案基本上完全放弃了浏览器控件渲染,而是采用原生自带的 UI 组件实现代替了核心的渲染引擎,仅保持必要的基本控件渲染能力,从而使得渲染过程更加简化,也保证了良好的渲染性能。也就是说,在泛 Web 容器时代,我们仍然采用前端友好的 JavaScript 进行开发,整体加载、渲染机制大大简化,并且由原生接管绘制,即将原生系统作为渲染的后端,为依托于 JavaScript 虚拟机的 JavaScript 代码提供所需要的 UI 控件的实体。这,也是现在绝大部分跨平台框架的思路。RN和Weex就是采用了这种设计方案。


泛web容器.png

为了追求更好的性能体验,进一步位置方案的简单可扩展性,一些公司已经放弃Web标准。放弃JS的动态执行能力,而自研一套原生的DSL解析器来实现跨端方案,例如天猫、美团、滴滴等。

自渲染引擎

泛 Web 容器方案使用原生控件承载界面渲染,解决了不少性能问题,但同时也带来了新的问题。抛开框架本身需要处理大量平台相关的逻辑外,随着系统版本变化和 API 的变化,我们还需要处理不同平台的原生控件渲染能力差异,修复各类奇奇怪怪的 Bug。始终需要 Follow Native 的思维方式,而Flutter 则使用了一种全新的思路,即从头到尾重写一套跨平台的 UI 框架,包括渲染逻辑,甚至是开发语言。

  • 渲染引擎依靠跨平台的 Skia 图形库来实现,Skia 引擎会将使用 Dart 构建的抽象的视图结构数据加工成 GPU 数据,交由 OpenGL 最终提供给 GPU 渲染,至此完成渲染闭环,因此可以在最大程度上保证一款应用在不同平台、不同设备上的体验一致性。
  • 开发语言选用的是同时支持 JIT(Just-in-Time,即时编译)和 AOT(Ahead-of-Time,预编译)的 Dart,不仅保证了开发效率,更提升了执行效率(比使用 JavaScript 开发的泛 Web 容器方案要高得多)。


    自渲染.png

通过这样的思路,Flutter 可以尽可能地减少不同平台之间的差异, 同时保持和原生开发一样的高性能。Flutter 成了三类跨平台移动开发方案中最灵活的那个,目前也是热度相对较高的跨平台方案。

我们的选择

对比三种方案最具代表的框架,我们可以对比他们不同的优劣


image.png

我们在做技术选型时,要从团队规模、开发效率、技术栈、性能表现、维护成本和社区生态来进行综合考虑。比如,是否必须支持动态化?是只解决 Android、iOS 的跨端问题,还是要包括 Web?对性能要求如何?对多端体验的绝对一致性和维护成本是否有强诉求?社区是否足够活跃,能够交流更多的疑难问题和解决方案,这些都是我们要考虑的。因为一旦选型后,业务的推动过程中,这些问题点最终都是要自己消化掉的。判断一个技术是否能成为未来大前端主流技术发展的趋势,主要看这个技术是否能减少对底层宿主环境的依赖,隔离各终端系统差异,能否从原理和运行机制及生态有领先同类产品的表现,向开发者提供统一而标准化的能力。

你可能感兴趣的:(flutter实践 - 跨平台的发展)