百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

前端开发:如何正确地跨端?(前端跨终端解决方案)

sinye56 2024-10-23 14:31 10 浏览 0 评论

简介: 面对多种多样的跨端诉求,有哪些跨端方案?跨端的本质是什么?作为业务技术开发者,应该怎么做?本文分享阿里巴巴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

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

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: