简介: 面对多种多样的跨端诉求,有哪些跨端方案?跨端的本质是什么?作为业务技术开发者,应该怎么做?本文分享阿里巴巴ICBU技术部在跨端开发上的一些思考,介绍了当前主流的跨端方案,以及跨端开发的经验心得。

跨端

Write once, run everywhere。

我们都听说过这句经典的宣传用语,后来我们都知道,没有什么东西是可以真正 run everywhere 的,充其量也只能做到 debug everywhere。

而当我们谈论一次编写多端运行时,显然不可能真的指跨一切所有端,大多数情况下你不会需要在电脑和手环上同步开发一个功能。

  • 跨 PC 和无线端。
  • 跨多 Native 平台:例如跨 Android 和 iOS,甚至跨 Windows。
  • 跨投放 APP:随着超级 APP 越来越多,很多业务需要在多个 APP 中投放同一个页面。
  • 跨 Web 和 APP:Web 在很多情况下仍然是不可避免的,我们的页面可能需要分享、SEO 或者投放到 M 站上等等,这时候就需要同时能在 Web 和 APP 内运行。
  • 跨 Web、多小程序、QuickApp 等:其实本来类似跨 APP,但是奈何小程序本身是各家控制的封闭生态,故而有了开发一次适配到多种封闭生态的诉求。
  • 其他端的跨端诉求:例如跨 POS 机,手表等。

与我们多种多样的跨端诉求相对应的,是百花齐放的跨端方案。

百花齐放的跨端方案

以 Web 为基础的 H5 Hybrid 方案

这类方案最为直接,简单来说就是用网页来跨端。由于我们绝大多数端上(甚至包括封闭的小程序生态)都支持 Webview,所以只要开发网页然后投放到多个端即可,在桌面端对应的方案就是 Electron。

为什么不直接全用 Web?

从开发成本低、标准统一、生态繁荣上来说,H5 Hybrid 方案基本是不二之选。然而这种方案难以避免在性能和体验上存在差距。Web 的生态繁荣来自于其良好的历史兼容性,也意味着沉重的历史包袱。

  • W3C 标准作为开放技术标准,历史包袱多,逻辑复杂。
  • Web 标准在设计上不是 Design for Performance 的,导致很多地方难以进一步改善,例如 JS 执行和 Layout、渲染互斥无法并行,导致过长的 JS 执行任务会执行正常的渲染导致卡顿。
  • Web 的标准化在推进上也比较慢,新的能力可能要比较长的时间才能使用。

React-Native/Weex 类方案

在移动平台上尤其是早期 WebView 的性能体验非常糟糕,前面我们也提到这种差距主要来自于 Web 生态本身沉重的历史负担。

而 React-Native/Weex 这类方案通过尽可能的取长补短,通过结合 Web 的生态和 Native 的组件,让 JS 执行代码后用 Native 的组件进行渲染。由于抛弃了 Web 的历史包袱,这类方案可以做一些大刀阔斧的改动。

例如 RN 就如下图中,把 JS 执行、布局(Yoga)和渲染(Native 组件)放在三个进程分开执行,避免了 JS 执行复杂任务时界面卡顿。通过抛弃 CSS 中的大量标准,只支持部分 flex 布局能力来减少布局和渲染的复杂度。

这种方案同样存在一些缺陷:

  • iOS/Android 双端本身不一致的组件和布局机制,让双端一致性难以得到保障。
  • 依赖于 Native 机制也让一些 CSS 属性实现起来比较困难,例如老大难的 z-index 问题。

而最麻烦的一点在于,这套方案意味着非常高的维护支持成本。

  • 借用了 Web 的生态但并不完全是 Web 生态,很多地方不一致,最常见的吐槽就是惯用的 CSS 布局方式无法使用。
  • 相比于浏览器新增一个传感器 API 都要配套完善的 devtool,这类方案大部分情况下的开发体验保障可以说是刀耕火种(下图为 Chrome 的方向传感器 API 的 devtool)。

在 WebView 性能差距逐渐缩小的今天,维护这一套复杂方案的 ROI 是否值得,需要根据我们场景的具体诉求考量。

Flutter

Flutter 要解决的问题和上面的方案不同,完全不打算继续在 Web 生态上借力,从设计之初也并没有把 Web 生态考虑进去。相比于 RN 依赖 Native View 渲染,Flutter 则是自绘的组件,直接通过 Skia 绘制到屏幕上。

由于可以完全发挥 GPU 的能力,也不需要去 Native 绕一圈。Flutter 理论上能做到更好的性能和两端一致性,这一意味着理论上未来可能基于 Flutter 的 JS 动态化方案能够在样式上支持的比 WEEX 更好。

从前端的视角看仍然更像是一个 Native 开发方案而非跨端方案(虽然其实是跨 Android/iOS 的)。目前最主要的问题是 Flutter for Web 从技术原理上来说离生产可用可能还非常遥远。除此之外动态化能力的确实也会让部分场景不适用。

研发框架 for 小程序

小程序是被创造出来的问题,各家小程序出于商业上的考量主动在 Web 生态的基础上构造了相对封闭的生态。导致和 Web 生态格格不入。然而有多端小程序投放,或者同时投放小程序和 Web 端的场景难以接受使用。

由于小程序的端封闭且不受控,要解决小程序的跨端问题往往只能从研发框架层面出发。

编译时方案

比较知名的编译时方案是 Taro,大致的原理可以解释为将 JSX 编译到小程序的 WXML/WXSS/JS 上,而这类框架的实现原理其实并非真的是一个 React 或者类 React 框架,而是把看起来像是 JSX 的模板通过静态编译的方式翻译成小程序自身的模板。

这样做的限制非常明显,那就是 JSX 是 JavaScript 的拓展语言(React Blog 写的是 is a syntax extension to JavaScript),而小程序所采用的 WXML 却是一个表达能力非常受限的模板语言,我们不可能完成从一个通用编程语言到模板语言的编译。

而静态编译类框架为了做到这一点,采取的方式就是限制开发者的写法,这也是为什么 taro 对 JSX 的写法做出了诸多限制。这一点直接导致了无穷尽的维护成本和严重受损的开发体验,而后 taro/next 也转向了运行时方案 + 静态编译优化的结合。

运行时方案

不谦虚的说,针对小程序的运行时方案应该是最早我在写下 remax 第一个 issue 时[1]提出的。

通过 React Reconciler(类似于 Rax Driver)我们可以让运行在小程序容器中的 React 不去直接操作 DOM,而是把操作的数据通过 setData 传递给小程序的 View 层映射到最后的界面上。

虽然 Remax、Rax 运行时、Taro Next 等几种方案不尽相同,但是思路大同小异,就是利用小程序模板一定程度上的动态化能力 + 类 React 框架的 VirtualDOM 来进行渲染。当然这种做法相对于小程序原生的渲染方式存在一定的性能损耗。

remax 的支付宝端性能测试

在部分场景下,这种损耗是值得的。这些运行时框架也都在陆续通过允许关掉编译产生的模板中的不用的属性、部分静态编译、虚拟列表等方式来改进性能。

当然了,最后内嵌 Webview 仍然是一个方案。

作为业务技术团队,我们该做什么

上面介绍的都是针对某些具体的场景的一些解决方案,然而对于业务技术团队来说,跨端的本质是提效。针对新的变化提出新的方案是一方面,更重要的如何让这种提效真的长治久安,让我们的提效不会变成从一个新方案跳到另外一个新方案。

让我们重新看上面这张图,可以确定的是,跨端的诉求和与之对应的方案仍然会处于频繁的变化中,也不会出现一个解决所有跨端问题的方案。而其中相对不变的部分是值得我们为了长治久安必须要投入的。

WebView & H5 Hybrid

WebView 可能是众多容器中最为特殊的一个,虽然很难满足部分场景对于性能和体验的极致要求,但是会是最稳定、长期存在且得到支持的方案。

从开发效率和未来长期的维护演变来看,在能够满足性能体验要求的前提下,Web 方案仍然是最优先应该考虑的。

同时,在 APP 的 WebView 容器上我们能做更多的工作,例如通过容器来提供一些端内的能力,结合 Native 能力实现的并行数据加载,页面保活等等。

基础建设

无论采用何种跨端方案,在哪个容器中,性能、稳定性、效能都是绕不开的三驾马车。

性能

对于不同的方案往往存在不同的性能方案,上面我们也提到在小程序的运行时方案中就会有减少编译模板产出的字段这样的优化。然而,其实除了这种特定方案的优化外,大部分优化手段是大同小异的:离线缓存、数据预取、快照、SSR、NSR 等等方案。

对于不同的端和容器,对于性能问题的度量和发现也应该是一致的,我们需要对页面在不同端的性能究竟如何有明确的感知和横向对比。

性能的端侧建设(端能力、具体到某一个端的性能测算方案、性能打点等)可能需要根据不同的端、不同的跨端方案而不同。但性能的基础建设(首屏标准、数据分析、基础优化能力)在跨端中应该是相对稳定的。

在端侧能力方面,ICBU 早期在 WEEX 性能优化时引入了并行加载的能力,通过 wh_prefetch 协议来使用容器的并行加载能力。而后在新的容器(WebView、浏览器)中,虽然底层能力存在差异,但仍然识别相同的协议。

在数据采集和分析方面,我们通过统一跨端基础库,让不同端不同技术方案可以在同样的标准下分析、度量和对比。

稳定性建设

在无线端我们常常把性能 & 稳定性并称为 “高可用”,稳定性主要涵盖的范围包括灰度能力、业务监控、报警、错误监控、白屏检测等等。

这些能力相比起来对具体端和跨端方案的依赖更少,除了在端侧的数据采集逻辑稍有区别外其他建设部分相对也是比较稳定的。集团针对这些场景也存在一些跨端可用的方案、例如 iTrace 等。

工程基建

对于不同场景的跨端,虽然在方案上存在一定的差异,但是我们的工程基建是可以保持统一

  • 容器层提供统一的 API 和文档能力
  • 统一的研发流程
  • 研发工具提供统一的抓包、debug 能力等
  • 一致的工具库等等

这样,当有新的容器或者方案出现时,我们只需要按照相应的能力进行对齐,就能让我们上层的业务代码和开发体验维持相对稳定的状态。

业务逻辑跨端

相对来说,我们会发现在多种跨端方案的演化中,如何渲染、如何布局等 UI 层面的变化要远远大于业务逻辑层面。甚至是小程序和 Flutter,其大致的开发范式都没有发生太大的改变。例如 Flutter 开发范式和 React 非常相似,同样是声明式 UI,同样存在 VirtualDOM。

考虑到 SEO 和性能等问题和 Flutter 本身基于 Skia 的渲染模式,Flutter for Web 在相当长一段时间内可能都不会是一个生产环境可用的方案。

而在统一了业务逻辑代码的组织方式后,我们可以通过 Hooks for ALL 的方案让 Flutter 和 Web 端可以共享一份基于 Hooks 的业务逻辑代码。

有时候你不需要真的 run everywhere,能够提高效能、保持一致就已经达到目的了。

视图层

目前来看视图层的跨端仍然充满了变数,在我们的业务逻辑层跨端做的足够原子化后,也许我们部分交互逻辑不是特别重的视图层能够通过 DX + 绑定原子化逻辑 + 数据参数的方式覆盖更多的跨端场景。从而同时满足性能、效能方面的诉求。

然而对于通用场景的视图跨端,仍然没有银弹。

总结

总体来说,跨端处于且将长期处于多方案并存且不断变化的状态。除了针对新的变化新的场景选择或创造合适的方案,我们更要做好这种动态变化中长治久安的部分:

  • H5 Hybrid。
  • 性能、稳定性、效能三驾马车的统一性和延续性。
  • 在不强求 write once 的场景下,考虑比 UI 跨端更简单的业务逻辑跨端。

作者:开发者小助手_LS

原文链接

本文为阿里云原创内容,未经允许不得转载

前端开发:如何正确地跨端?相关推荐

  1. 快速入门Web前端开发的正确姿势

    入门标准很简单,就一条:达到能参与 Web 前端实际项目的开发水平.请注意,是实际项目,这就需要了解如今的实际项目开发都用了哪些技术栈.HTML/CSS/JavaScript 这三大基础技术栈肯定是需 ...

  2. 前端开发如何独立解决跨域问题

    前端开发如何独立解决跨域问题 参考文章: (1)前端开发如何独立解决跨域问题 (2)https://www.cnblogs.com/softidea/p/7425894.html 备忘一下.

  3. 前端技术周刊 2019-01-21:跨端开发的三条路线

    2019-01-21 前端快爆 微软 Edge 开发者意图为 Chrome 实现 HTML Modules,该规范用来替代之前的 HTML Imports.其优点是基于 ES Modules,可以避免 ...

  4. 最详细,快速入门Web前端开发的正确姿势

    入门标准 入门标准很简单,就一条:达到能参与 Web 前端实际项目的开发水平.请注意,是实际项目,这就需要了解如今的实际项目开发都用了哪些技术栈.HTML/CSS/JavaScript 这三大基础技术 ...

  5. es6标准入门第3版pdf_最详细,快速入门Web前端开发的正确姿势

    入门标准 入门标准很简单,就一条:达到能参与 Web 前端实际项目的开发水平.请注意,是实际项目,这就需要了解如今的实际项目开发都用了哪些技术栈.HTML/CSS/JavaScript 这三大基础技术 ...

  6. 前端开发的正确姿势——各种文件的目录结构规划及引用

    首先,要说的是我们领导总挂在嘴边的一句话:一入前端深似海.之前没有接触过前端,一直不懂这句话的含义,直到最近写作业改需求的时候才发现,因为web页面是直接面向客户的,所以需求的修改都和前端有关,有时候 ...

  7. 【小程序专栏】多种开发方式对比-跨端?低代码?原生?还是云开发?

    目前"小程序"的开发与应用呈现"井喷"之势,作为小程序的鼻祖,2021年微信小程序开发者突破了300万,日活跃用户数(DAU)已经超过4.5亿,微信为开发者支付 ...

  8. 前端开发跨浏览器计算页面大小、滚动高度

    前端开发中跨平台.跨USER-AGENT的适配很繁琐 想要得到浏览器px大小非常烦.因此以下2个函数非常实用 这两个javascript函数很有用,用来计算浏览器页面大小,窗体大小,以及滚动高度,源码 ...

  9. 干货 | 携程机票 App KMM 跨端生产实践

    作者简介 禹昂,携程移动端资深工程师,Kotlin 中文社区核心成员,图书<Kotlin 编程实践>译者. Derek,携程资深研发经理,专注于移动端开发,热衷于各种跨端技术的研究和实践. ...

最新文章

  1. [20180408]那些函数索引适合字段的查询.txt
  2. android 高级画布绘图
  3. Sun公司因为不懂销售和运营,导致陨落,最终软件还是打败了硬件
  4. tar命令核心应用案列及多重参数和find组合应用
  5. 现代软件工程系列 学生的精彩文章 (3) 如何在Bug 不断的情况下还能保持平常心...
  6. 虚拟ip工具_《跟唐老师学习云网络》 - ip命令
  7. 简单理解L0、L1与L2范数
  8. java随机函数用法Random(转)
  9. 如何使用powerdesigner导出sql脚本
  10. 二叉树的创建及遍历_递归遍历_非递归遍历
  11. z blog php版本怎么样,Z-BlogPHP版本可能用到的SQL语句整理
  12. SharePoint 站点集和子站点数据互相读取
  13. 谷歌大牛 Jeff Dean 是如何成为互联网战神的
  14. 【转载】java版打字练习软件
  15. 最好的贵人,是努力的自己
  16. SEO工作者面试基本都会被问到的问题
  17. linux环境中设定开机自启动与定时任务
  18. ROS2 基础概念 参数
  19. 【Linux】常见指令汇总
  20. 震惊!!十五天开发出一款安卓打卡app,并且成功发布!

热门文章

  1. bga bond焊盘 wire_封装模式: FC-BGA VS. WireBond ,谁是封装工艺中的真英雄?(图)
  2. java调用扫描仪_通过Java调用Dynamsoft .NET TWAIN SDK控制扫描仪扫描文档
  3. 【历史上的今天】7 月 7 日:C# 发布;Chrome OS 问世;《仙剑奇侠传》发行
  4. 今日金融词汇---专利护城河
  5. [再寄小读者之数学篇](2014-06-23 向量公式)
  6. 来自东南亚的极兔被“封杀”,老家还能保住吗?
  7. 快速搜索随机树(RRT---Rapidly-exploring Random Trees)入门及在Matlab中演示
  8. Calico 报错 calico/node is not ready: BIRD is not ready: BGP not established with(导致 K8S 集群网络无法使用)
  9. docker启动es报错:failed to obtain node locks...
  10. uCOS2的events事件源码分析-第4季第5部分-朱有鹏-专题视频课程