写点什么

大前端的下一站何去何从?

  • 2019-01-18
  • 本文字数:5142 字

    阅读完需:约 17 分钟

大前端的下一站何去何从?

近年来,移动互联网应用有着爆发式的增长,同质化 APP 层出不穷,人们对于产品体验的要求越来越高,渲染迟缓、交互卡顿的单体 Web APP 已经无法满足现有用户苛刻的使用标准;与此同时,井喷式的业务需求迫使 iOS、Android 两个移动平台不断提升迭代开发速度,缩短版本发布周期;如何既能利用 Web 门槛低、轻量级、跨平台开发的优势,又能尽可能最大化屏蔽其现存缺点成了大前端融合领域攻克的重点。


本文借用主流移动跨平台开发方案,向大家介绍移动平台开发的演变之路。

Hybrid-App 的天下

移动应用开发领域发展至今已基本被 Android、iOS 两大平台统治,每个平台仍在不断发展完善、壮大自己的生态系统;对开发者而言每个平台更像是一个巨大的 SDK,为我们抹平了设备硬件、系统内核所带来的差异,统一了平台设计、开发方式。



Figure 1 移动开发平台概览


为了追求极致的开发效率、降低研发成本,早期的开发者不断尝试利用新技术突破平台所带来的约束,PhoneGap 技术(旨在让早期的 Web-App Written once, run everywhere )的出现让开发者们看到了 Hybrid-App 的雏形。


PhoneGap 技术基于 WebView 引擎中的 JS Core 解释器,其核心是 Cordova JavaScript 类库,这层 JavaScript Plugin 抹平了不同平台间的差异,为 Web 与 Native 交互提供了统一的抽象接口及完善的调用机制,其本质是将不同平台打造为一个接口统一的 Web 壳资源平台:UI 渲染依赖平台 Web Render 处理,统一使用 HTML+CSS 绘制;交互逻辑使用 JS Core 这种方式在早期大大降低了开发成本、同时也缓解了早期特定移动平台开发人员稀缺的问题,早期定义的 Hybrid-App 更像是基于移动平台开发的 Web App。



Figure 2 基于 PhoneGap 开发的移动 APP


伴随业务规模的发展,人们发现这种方式虽然高效,但是用户体验却是一团糟;虽然实现了跨平台开发,但又被有限的插件资源所限制;移动开发领域初期,系统平台众多,一系兼容处理让整个框架变得臃肿,这令原本就性能堪忧的框架更是捉襟见肘。随着前端技术的进步,开发者们也在不断打磨 Cordova 框架:提升整体加载性能、增强插件扩展灵活性,从大刀阔斧到精雕细琢,Cordova 生态系统逐渐完善, 众多公司也纷纷开始围绕 Cordova 及一些主流的前端框架打造自己的专属移动开发平台,Hybrid-App 也从青涩步入成熟。



Figure 3 基于 Cordova Plugins 的主流 Hybrid APP 框架


这里不得不提到影响了近几年前端设计思想的 UI 框架 React.js,其设计初衷是优化 web 在移动端的渲染性能、改变传统的 UI 开发方式:


组件的概念 - React 基于 UI 组件构建视图,每个组件负责维护自己的(State)展示状态,利用简单的 UI 组件创建复杂的 UI;利用组件组合后形成的单向数据流,根据 State 的变化来刷新 UI 展示;同时推出了更便于组件化开发的 JSX(JS 语法糖) 语言。


Visual DOM - React 一个颠覆性的创新就是引入了二进制 Visual DOM 树,其本质可以理解为在 JS 和 DOM 之间做了一个缓冲层用于保存 Virtual DOM 树,UI 状态变化时只比较新旧 Visual DOM,通过 Diff 算法找出节点差异,然后进行真实 DOM 操作。因为操作 HTML DOM 是非常耗费系统资源的,通过这种方式可以保证以最小代价刷新 UI。


轻量级的 UI 框架 - 可以和其他前端框架结合使用,React.js 只是单纯的 UI 框架,也就是常说的 MVC 框架中的 View 层,它借用了响应编程模式的特点来简化 Web 视图的创建过程;Model 层 和 Controller 层的缺失催生出了 Flux 和 Redux(Redux 可以视为 Flux 框架的精简版) 框架。


这里仅以使用比较广泛、知名度更高的 Redux 框架来介绍,Redux 框架的核心理念是严格的单向数据流,只能通过 dispatch(Action) 的方式修改 Store 数据(Store 的概念源自 MVCS 框架,Store 不仅仅是 Model 的概念,理解为前端中的 DB 形式更为贴切),其流程可以简单描述为:View -> Action -> Reducer(logic process) -> Store(change/write/delete state)。


Redux 的设计理念是不是看上去和 React.js 不谋而合?再加上 Redux 社区还基于异步流扩展了很多 Extensions 插件(redux-trunk、redux-promise、redux-saga、redux-observable 等),所以很多厂商纷纷选用 React+Redux 作为自己的 Web 支撑框架。


至此,也就形成了业内主流的 Hybrid-App 框架 Cordova+React+Redux,但是由于 Web 有着先天的局限性,前端框架只是从架构设计、算法层面对性能进行优化,仍然无法解决根本问题:


  • 首次渲染效率及白屏问题

  • 单线程的状态分发机制,无法满足复杂用户交互场景(滑动,拖动手势)

  • 伴随着业务规模持续增长的 js plugin,基于单 Web 页面的注入机制,无法有效控制内存增长

  • React.js 这种依托于算法优化渲染效率前端框架,也有着无法回避的缺陷:

  • 首次创建 Virtual DOM 树的耗时相当于延迟了首屏渲染时间

  • 每次 State 变化都会生产全量 Virtual DOM 树,和上一次结果做 diff,这其实是一次算法执行时间与 Real DOM 操作时间的博弈

  • 需要编写大量的闭包函数(Redux 也有同样的缺陷)


随着业务爆发式的增长、交互复杂度提升、数据请求不断增多,如果要 Redux 承载整个 App 或大部分关联 Web 的数据处理已经非常困难:


  • Store 中存放的冗余数据越来越多,维护了多个 Web 页面的组件状态

  • 直接在 reducer 中操作 View 与 Model,几层 reducer 之后很难明确 Model 已经被加工成何种形式

  • 一直会有下一个基于 Redux 的改良封装 Extensions

  • 异步、同步相互依赖场景,复杂 UI 交互,恐怕大部分精力都在考虑 reducers 怎么拆分了


不可否定的是,React 和 Redux 是伟大的框架,他们设计思想、核心理念对后续移动领域的发展有着深刻的影响;移动互联网技术的发展反而放大了它们的先天缺陷,这也加快了 Hybrid-App 的进化速度。

不甘平庸的产物

在 W3C 制定 HTML5 标准之初,FB 的创始人扎克伯格就曾口出狂言要用 HTML5 技术统一移动端,无奈宣告最终押注失败,随后 React、Redux Web 框架的相继推出表明了他们并未真正放弃,这也为 2015 年 FaceBook 发布 React Native 框架买下了伏笔。


一心想统一移动端开发的 FaceBook 在 2015 年宣布了只用 JS 语言开发 Native 应用的框架 React Native(后文称:RN),并提出了新的口号:Learn once write anywhere,新框架强调的是 UI 绘制、交互逻辑思想、开发方式的统一,与 Cordova 不同的是 RN 将 JS 中定义的组件标签都转义成了原生对应的 UI 组件,直接抛弃了 WebKit 中渲染、绘制功能,全部使用 Native 资源,其核心思想是基于 JavaScript 虚拟机将 JSX 编写的组件映射为 Native UI 组件。由于 RN 技术天生就引用了自家的 React.js 技术框架又有整合了 Native 平台 UI 组件,在发布之初让广大前端开发者看到了新的希望。


不同平台的 JS 虚拟机为 RN 提供运行时 JS Context 环境,其中注入了 RN 转义 Native UI 组件的接口,相较于传统的 Cordova 形式的 Hybrid-APP,不深究细节的话,可以认为 RN 使用了原生 UI 组件完美替换了 Web Core 中的 H5 + CSS 的绘制框架。



Figure 4 React Native 跨平台开发框架


由于使用了原生 UI 组件,其渲染速度和 UI 流畅度有了质的飞越,前期很多 Web 页面无法支持的效果也可以使用 RN 来实现;只使用 JS/JSX 开发,兼容 Web React.js、Redux.js 等主流框架,RN 自身也实现了大部分 UI 组件的集成工作,再借助活跃的社区,开发效率相比于原有的 Native+Web 形式的 Hybrid-App 有了显著提升。


虽然 RN 在发布早期备受关注,甚至一些互联网企业已经发布了 RN 的商业化平台,但是业内仍然出现了“RN - 由入门到放弃”的声音,究其原因,主要可以归结为以下几类:


  • 无法完全抹平跨平台 JS Engine 的差异性,JavaScript Core 的不一致性,RN 的 Android 版本仍然不支持 ES6 的 JSC

  • 发布快四年之久,仍为 0.x 版本,还不能满足 1.0 版本的稳定性(近期 Facebook 又在对 RN 进行大规模重构)

  • RN 社区开源库质量参差不齐,很容易跳进坑里

  • 很多基础框架的库还是不支持 RN,需要自己封装

  • 学习成本高,为了输出一个稳定的版本既要熟悉 iOS 平台特性又要兼顾 Android 平台兼容性

  • 启动时间长,向单一 JSC 中注入一段庞大的 js 插件仍然需要很长时间,即便只是注入基础插件库

  • RN 框架每一次版本升级所带来的接口向下兼容问题

  • JS 是单线程的解释性语言,手势、动画仍然是无法解决的痛点

  • Android 9.0 已经开始着手对插件进行主动封堵,这也会给各种形式 Hybrid 带来一定影响


Facebook 起初正是考虑到不同浏览器 WebKit 内核的差异性以及 web view 所造成的内存、性能损耗,所以才决定仅仅基于 JS VM,只使用单一的 JavaScript 语言来完成跨平台开发的统一,却忽视了不同平台系统、版本所带来的差异;还有就是 JS 解释性语言先天的单线程执行所带来的硬伤,始终无法屏蔽 JS VM 的效率损耗;有没有哪种框架可以避免这种硬伤,又能满足跨平台开发的需求呢?搅局者 Flutter 出现了。

搅局者

Google 这种以创新为本的公司当然不满足于 RN 这种带有瑕疵的框架,Google 开启了 Flutter 框架的开发,至今已发布 1.0 Release 版本。Flutter 从设计初期就选用可编译成机器码的 Dart 语言开发并且决定将 UI 组件和渲染器从平台移动到应用层中,直接避免了由 JavaScript Bridge 引起的性能问题并最大可能降低了系统平台的差异。



Figure 5 Flutter 跨平台开发框架


Flutter 实际上是在已有移动平台中搭建了一套独立的开发系统,它也是至今为止唯一提供响应式视图而不需要桥接器的移动 SDK,Flutter 唯一要求是系统提供的 Canvas 、访问事件(触摸、定时器等)和服务(位置、相机等)。其整体架构设计可以总结为一下几点:


1.一切皆为 Widget,这与 React 中一切皆为组件类似,不过 Widget 承载的定义更广泛一些;


2.使用 Google 自家的 Dart 语言开发 Flutter Widget,Dart 语言的主要特性就是可编译为机器码,无需依赖桥接器;


3.Flutter 框架在设计上引入了分层结构,每一层都简历在前一层之上,并且开源全部框架代码(个人认为在 Preview 版本全部开源并不利于生态发展);


4.Flutter 直接基于 GPU 引擎绘制,抛弃系统 UI 组件(原文引用:借助可移植的 GPU 加速的渲染引擎以及高性能本地 ARM 代码运行时以达到跨设备跨平台的高质量用户体验);


5.Debug Mode 支持 hot reload,减少开发阶段编译、调试时间。


Flutter 框架因为直接基于 Canvas 开发,这也显著降低了在旧版本操作系统上进行兼容性测试的需求;Dart 也拥有和 NPM 类似的软件包仓库,这些软件包也可以扩展当前应用的能力。想为开发者打造一套独立的开发框架,当然你也会猜测到,Flutter 框架不会太完美:


  • Dart 语言的嵌套地狱

  • 由于 Dart 编译器使用了 tree shaking 等技术,也因而在 Flutter 中禁止了 Dart 支持的反射特性

  • Flutter 无法使用 iOS、Android 自带的设计样式

  • 将 Flutter 开发框架植入现有 iOS、Android 开发工程要做很多适配工作

  • 完全开源的 preview 框架让人担忧其框架生态的健康发展

涨乐现有 Web 容器方案

涨乐 APP(华泰证券旗下的应用)受限于现有架构和业务需求,对于 RN、Flutter 等框架保持谨慎的态度。我们当前采用 Hybrid 形式进行开发,交互复杂、安全要求较高、内存资源占用高的业务(如:行情、交易、活体检测、双向视频等)均由 Native 开发;场景比较单一、样式频繁变更、交互简单的需求页面则使用 Web 开发。


涨乐 APP 中现有的 Web 框架并未采用 jsBridge 注入的方式,而是仿造 Spring 的设计思路,将现有 Native APP 打造为了一个 Local Server 平台,将 Native 功能打造为一个个独立的 Service 组件,仿造 Rest 接口统一 Native -> Service、Web -> Service 调用协议;Web 开发人员基于 Ajax 调用不同的 Service 组件,LocalServer 负责分发不同的 Service。


涨乐 APP 基于平台优势,拦截了现有 Web 资源加载、请求协议,扩展了 Web 资源的能力及生命周期,避免了传输重复资源耗时;也正是因为有了 Web 拦截机制,涨乐 APP 可以在 Web 容器 初始化的同时进行资源下载操作,这样有效缩短了先初始化容器再下载资源的时间损耗。


相比如 Cordova 方式的优点:


  • 利用现有移动平台特点,牺牲 Service 调用分发时间换取对内存空间,尽可能减少注入 js 插件体积

  • 仿 Spring 框架打造的 Local Server 平台,基于 Service 打造 Native 支撑

  • Web 资源加载协议拦截机制,避免冗余资源文件传输,加速

总结

本文借用几个主流框架简单介绍了大前端跨端技术框架的发展线路,随着移动应用开发技术的不断发展、成熟,最终会形成一套稳定、统一的跨平台开发体系; 开发者对于 web 容器增强、业务插件化、虚拟运行环境等技术框架的不断深耕、雕琢也都在推进大前端技术朝着一个统一的方向前进 – 多端融合。我们只能通过不断的技术积累、输出,才能追赶上大前端变革的浪潮,让业务更好地依托技术为用户提供更优质的产品体验。


更多内容请关注前端之巅(ID:frontshow)



2019-01-18 09:5211599

评论 5 条评论

发布
用户头像
安利一款我用过最好用的接口测试工具——apipost ,页面简洁,操作简单功能也多。
2021-08-27 16:44
回复
用户头像
此文写的特别好,尤其对于react tn redux的分析非常精准。对于flutter目前保持观望,主要是对google的不信任,以及对于dart的存疑,如果是用es6或者ts我肯定就上车试试了。flutter的material design的实现其实最让我心动,要是能给rn也实现一套就好了。
关于Android 9.0的封闭趋势能谈一谈吗? 另外作者提到的自己使用的技术方案能详细说说嘛?尤其是local server化的部分,非常期待。
2019-01-28 11:21
回复
用户头像
完全开源的 preview 框架让人担忧其框架生态的健康发展? 这个担忧很特别,有隐情没讲清楚?
2019-01-23 14:14
回复
用户头像
为什么没有weex
2019-01-20 00:18
回复
等ali自己用了再说吧,之前弄得鸡飞狗跳的听说。
2019-01-28 11:21
回复
没有更多了
发现更多内容

编程实战:如何管理代码里的常量

华为云开发者联盟

常量 代码 web开发 final常量类 复用常量

浅谈BSS3.0产品“守成”之策下 • 运维提升篇

鲸品堂

软件 运维 提升

使用 rocketmq-spring-boot-starter 来配置、发送和消费 RocketMQ 消息

阿里巴巴云原生

容器 开发者 云原生 中间件 API

新思科技发布《疫情中的安全隐患:移动应用程序安全现状》报告

InfoQ_434670063458

App 新思科技 移动应用程序安全

架构实战营 - 架构设计文档模板

华仔

架构设计 文档模板

亲爱的开发者,您收到一个启动智能世界的魔方

白洞计划

边缘计算加持下的智慧社区

边缘计算

Pytorch数据加载

Sakura

4月日更

源中瑞智慧党建系统,打造党建管理系模式

13530558032

LeetCode题解:73. 矩阵置零,栈,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

区块链电子签章应用平台--助推企业数字化转型升级

13530558032

面对大规模 K8s 集群,如何先于用户发现问题?

阿里巴巴云原生

容器 云原生 k8s 监控 调度

图算法系列之深度优先搜索(一)

Silently9527

Java 深度优先搜索 图算法

量化策略系统搭建,马丁策略交易

扩展 GRTN:云原生趋势下的 RTC 架构演进

阿里云视频云

阿里云 云原生 RTC SRS流媒体服务器

Coinbase上市意味着什么?

猫Buboo

马斯克的狗狗币实验

猫Buboo

合约交易所跟单,合约跟单社区开发

区块链食品溯源--为食品溯源认证

13530558032

RocketMQ NameServer工作原理与源码解析

HByte

RocketMQ

PassJava 初始化项目和添加微服务

悟空聊架构

ndk开发环境,个人开发者做一款App需要知道的事情,绝对干货

欢喜学安卓

android 程序员 面试 移动开发

游戏测试-战斗内核的自动化测试

行者AI

人工智能

手把手教你写一个经典躲避游戏

HZFEStudio

大前端 游戏 canvas

如何推进一个“以行动为导向的”事件驱动架构?

VoltDB

数据库 数据分析 实时数据分析 事件驱动架构

闲来无事,写脚本,install_wordpress

ilinux

NumPy之:标量scalars

程序那些事

Python 数据分析 Numpy 程序那些事 scalar

mmkv跨进程,面试字节跳动Android研发岗,灵魂拷问

欢喜学安卓

android 程序员 面试 移动开发

40个问题让你快速掌握Java多线程的精髓

华为云开发者联盟

Java 多线程 synchronized Thread Semaphore

用C++ 和OpenCV 实现视频目标检测(YOLOv4模型)

博文视点Broadview

B站HR炫耀资产、贬低面试者?无独有偶,校招污点事件记录帮你避雷

北游学Java

Java 面试

大前端的下一站何去何从?_移动_华泰证券互联网前端团队_InfoQ精选文章