当前位置: 首页 > Web前端 > CSS

前端开发:如何正确跨端?

时间:2023-03-30 14:30:52 CSS

介绍:面对各种跨端需求,有哪些跨端解决方案?跨端的本质是什么?作为业务技术开发人员,您应该怎么做?本文分享阿里巴巴ICBU技术部对跨端开发的一些思考,介绍目前主流的跨端解决方案,以及跨端开发的心得体会。跨端编写一次,到处运行。这个经典的slogan我们都听过,后来也都知道没有什么东西真的可以到处跑,充其量也只能是到处debug。而当我们说一次在多个终端上编写运行时,显然不可能真正指代所有终端。在大多数情况下,您不需要同时在电脑和手环上开发一个功能。跨PC和无线。跨多个Native平台:比如跨Android和iOS,甚至跨Windows。交叉交付应用:随着越来越多的超级应用,许多企业需要在多个应用中启动同一个页面。跨Web和APP:Web在很多情况下还是无法避免的。我们的页面可能需要分享,SEO或者放在M站等等,这时候就需要能够在Web端和APP端运行。跨web、多应用、快应用等:其实和跨应用类似,但是小程序本身是一个封闭的生态,由各个公司控制,所以需要同时适配多个封闭生态时间。其他终端的跨终端诉求:比如跨POS机、手表等。对应我们各种跨终端的需求,也有跨终端的解决方案百花齐放。百花齐放的跨端解决方案是基于Web的H5Hybrid解决方案。这种解决方案是最直接的。简单的说就是利用网页进行跨端。由于我们的大部分终端(即使是封闭的小程序生态)都支持Webview,所以我们只需要开发网页,然后放到多个终端上即可。桌面上对应的解决方案是Electron。为什么不让所有人都使用网络呢?在开发成本低、标准统一、生态繁荣方面,H5Hybrid方案基本上是最佳选择。但是,该方案难以避免性能和体验上的差距。Web生态的繁荣源于其良好的历史兼容性,同时也意味着沉重的历史包袱。W3C标准作为一个开放的技术标准,有着诸多的历史包袱和复杂的逻辑。Web标准不是为DesignforPerformance设计的,这使得很多地方难以进一步完善,比如JS执行、布局、渲染互斥不能并行,导致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的devtool)方向传感器API)。在WebView性能差距逐渐缩小的今天,是否值得维持这个复杂方案的ROI,需要根据我们场景的具体需求来考量。FlutterFlutter要解决的问题与上面的解决方案不同。它根本不打算继续借助Web生态,从设计之初就没有考虑Web生态。与依赖NativeView渲染的RN相比,Flutter是一个自绘组件,通过Skia直接绘制到屏幕上。既然可以充分发挥GPU的能力,就没必要绕着Native走。Flutter理论上可以在两端实现更好的性能和一致性,这意味着理论上,未来基于Flutter的JS动态方案可能支持比WEEX更好的样式。从前端的角度来看,它仍然更像是一个Native开发方案,而不是一个跨端方案(虽然实际上是跨Android/iOS)。目前的主要问题是,FlutterforWeb在技术原理上可能离生产可用性还有很远的距离。另外,动态能力确实会让一些场景变得不适用。小程序研发框架小程序是一个创造的过程,各个小程序出于商业的考虑,在Web生态的基础上主动构建一个相对封闭的生态。因此,它与Web生态不兼容。但是,小程序多端投放,或者小程序和Web端同时投放的场景,是很难接受的。由于小程序端封闭且不可控,解决小程序的跨端问题只能从研发框架层面入手。编译时解决方案著名的编译时解决方案是Taro。大致原理可以解释为将JSX编译成小程序的WXML/WXSS/JS,这类框架的实现原理并不是真正的React或React-like框架,而是通过静态编译的方式,将看起来像JSX的模版翻译成小程序本身的模版。这样做的局限性非常明显,就是JSX是JavaScript的扩展语言(ReactBlog写的是对JavaScript的语法扩展),而小程序使用的WXML是模板语言,表达能力非常有限。可以完成从通用编程语言到模板语言的编译。为了实现这一点,静态编译类框架采用了限制开发者写法的方式,这也是taro对JSX的写法做了很多限制的原因。这直接导致了无穷无尽的维护成本和开发体验的严重受损,随后taro/next也转向了运行时解决方案+静态编译优化的组合。runtime的解决方案我不敢说小程序的runtime的解决方案应该是我在写remax[1]第一期的时候最先提出来的。通过ReactReconciler(类似于RaxDriver),我们可以避免运行在小程序容器中的React直接操作DOM,而是将操作后的数据通过setData传递给小程序的View层映射到最终的界面。Remax、Raxruntime、TaroNext等解决方案虽然不同,但是思路是相似的,就是在一定程度上利用小程序模板的动态能力+类React框架的VirtualDOM进行渲染。当然这种方式相比小程序原生的渲染方式有一定的性能损失。在remax的支付宝性能测试的一些场景下,这样的损失是值得的。这些运行时框架还通过允许关闭由编译、部分静态编译、虚拟列表等生成的模板中未使用的属性来提高性能。当然,最终嵌入Webview还是一个解决方案。作为业务技术团队,我们应该怎么做?以上是针对特定场景的一些解决方案。但是,对于业务技术团队来说,跨终端的本质是提高效率。为新的变化提出新的解决方案是一方面,更重要的是如何让这种效率提升真正长久,让我们的效率提升不会变成从一个新方案跳到另一个方案。我们再看看上图。可以肯定的是,跨终端的诉求和相应的解决方案还是会经常变化,不会有一个解决所有跨终端问题的方案。为了长期稳定,相对不变的部分值得投资。WebView&H5HybridWebView可能是众多容器中最特殊的一个。虽然在某些场景下难以满足对性能和体验的极致要求,但它会是最稳定、最长久、最受支持的解决方案。从开发效率和未来长期维护演进的角度来看,在满足性能体验需求的前提下,仍然应该优先考虑Web方案。同时我们可以在APP的WebView容器上做更多的工作,比如通过容器提供一些端到端的能力,结合Native能力实现数据并行加载,页面保活等。无论基础设施建设采用什么样的跨端方案,在哪个容器中,性能、稳定性、效率都是绕不开的三驾马车。性能不同的解决方案往往有不同的性能方案。上面我们也提到,在小程序的runtime方案中,会有减少编译模板产生的字段等优化。但是除了针对这个具体的方案进行优化外,大部分的优化方式都是类似的:离线缓存、数据预取、快照、SSR、NSR等方案。对于不同的码头和集装箱,性能问题的测量和发现也应保持一致。我们需要对页面在不同终端上的表现有清晰的感知和横向对比。性能的端到端构建(端能力、某一端的具体性能测量方案、性能管理等)可能需要针对不同的端和不同的跨端方案而有所不同。但性能的基础建设(首屏标准、数据分析、基础优化能力)应该是跨终端相对稳定的。在端侧能力方面,ICBU早期在WEEX性能优化中引入了并行加载能力,通过wh_prefetch协议使用容器的并行加载能力。那么在新的容器(WebView、浏览器)中,虽然底层能力不同,但是识别的还是同一个协议。在数据采集和分析方面,我们统一了跨端的基础库,让不同端的不同技术方案可以在同一个标??准下进行分析、衡量和比较。稳定性建立在无线方面。我们经常将性能和稳定性一起称为“高可用性”。稳定性主要包括灰度能力、业务监控、告警、错误监控、白屏检测等。与这些能力相比,它们对特定的端到端和跨端解决方案的依赖程度较低。除了端侧的数据采集逻辑略有不同外,其他构建部分都比较稳定。集团也有针对这些场景的一些跨终端可用的解决方案,比如iTrace等。虽然不同场景下跨端工程基础设施的解决方案存在一定差异,但我们的工程基础设施可以维护一个统一的容器层,提供统一的API和文档能力。统一的研发流程研发工具提供统一的抓包、调试能力等一致的工具库等,这样当出现新的容器或者解决方案的时候,我们只需要按照相应的能力进行对齐,让我们的上层业务代码和开发经验可以保持一个相对稳定的状态。相对而言,在业务逻辑的跨端,我们会发现在各种跨端方案的演进中,UI层面的变化,比如如何渲染,如何布局,远大于业务逻辑层面的变化。.即使是小程序和Flutter,一般的开发范式也没有太大变化。例如,Flutter的开发范式与React非常相似。它也是一个声明式的UI,VirtualDOM也存在。考虑到SEO和性能以及Flutter自身基于Skia的渲染模式等问题,FlutterforWeb可能在相当长的一段时间内都不是生产环境可用的解决方案。统一业务逻辑代码组织后,我们可以使用HooksforALL方案,让Flutter和Web端共享一个基于Hooks的业务逻辑代码。有时候你真的不需要到处跑,能够提高性能和保持一致性就足以达到目的了。视图层目前,视图层的跨端仍然充满变数。在我们的业务逻辑层跨端充分原子化之后,也许我们一些交互逻辑不是特别重的视图层可以采用DX+绑定原子化逻辑+数据参数的方式覆盖更多的跨端场景。从而同时满足性能和效率的需求。但是,在一般场景下视图跨端仍然没有灵丹妙药。总结一般来说,跨终端在很长一段时间内都处于并将长期处于多程序并存、不断变化的状态。除了针对新变化、新场景选择或创建合适的解决方案外,还要做好这种动态变化的长期稳定性:H5Hybrid。性能、稳定性、效率三驾马车的统一性和连续性。在不需要writeonce的场景下,考虑比UI跨端更简单的业务逻辑跨端。作者:开发助手_LS原文链接本文为阿里云原创内容,未经允许不得转载