.

写给前端的跨平台方案跨端引擎的本质

作者:神说要有光zxg来源:神光的编程秘籍

近些年来,前端领域的跨端技术越来越多了:reactnative、weex、flutter、electron、kraken等等。

那么多跨端方案,他们有没有通用的思路?我们能不能从这么多方案中找出本质的原理?

本文会尝试探究探究以下问题:

什么是跨平台

有哪些方案是跨平台的

跨端和跨平台的区别是什么

前端领域有哪些跨端方案

跨平台、跨端的通用原理是什么

什么是跨平台

我们知道,cpu有不同的架构和指令集,上层也有不同的操作系统,一个系统的可执行文件在另一个系统上就是不可执行的,比如windows的exe文件在mac上就不能直接执行。不同的系统就是不同的运行平台。可执行文件是不跨平台的。

不同平台提供的api不同,所以代码逻辑可能也不同,需要不同平台单独维护代码。这样就带来了几个问题:

多平台各自开发,怎么保证功能是一致的

多平台各自开发,那是不是得各自测试,开发和测试的人力都是多份的

所以出现了跨平台的一些技术,目标是一份代码跑在任意平台。

我们先来看一些各领域的跨平台方案:

浏览器

操作系统不同,浏览器上跑的网页的代码确实同一份。浏览器就是一种历史悠久的跨平台方案。

网页跨平台不意味着浏览器也是跨平台的,浏览器的可执行文件还是每个平台单独开发和编译的,但是他们支持的网页解析逻辑一样,这样上面跑的网页就是跨平台的。

浏览器提供了一个容器,屏蔽了底层差异,提供了统一的api(domapi),这样就可以实现同一份代码跑在不同平台的统一的容器里。这个容器叫做浏览器引擎,由js引擎、渲染引擎等构成。

docker

docker是一种虚拟化技术,可以在操作系统之上加一个虚拟层,在这层之上划分一到多个容器,容器里再去跑系统、app,这样可以实现硬件和软件的分离,动态分配硬件资源给容器,并且方便app运行环境的整体迁移(保存成镜像)。

docker很明显也是一种跨平台技术,同一个镜像可以跑在任何操作系统的docker上。只要不同操作系统实现同样的容器即可。

jvm

java是一门编译+解释的语言,java源码编译成字节码,然后字节码直接在vm上解释执行。

java为什么这么火呢?主要是因为跨平台。

c、c++这种语言写的代码需要编译成不同操作系统上的可执行文件来跑,而且每个平台的代码可能还不一样,需要写多份。

java因为提供了jvm容器,只要把源码编译成jvm能解释的字节码就行了,而且jdk提供了统一的api,分别由不同操作系统的底层api来实现,这样对于java代码来说,不同操作系统的代码是一致的。

jvm也是通过容器的技术实现了一份代码跑在多个平台,而且jre提供了统一的api,屏蔽掉了底层的差异。

node、deno

node和deno也是跨平台的技术,通过提供一套一致的api,让其上的js代码可以跨平台。这些api也是不同平台各自实现的。

electron

electron内置了chromium,并为其注入了node的api和一些GUI相关的api,是基于两大跨平台技术综合而成的跨平台方案。基于这些方案的组合使得electron支持用前端技术开发桌面端。

跨平台方案的优缺点

跨平台方案的优点很明显,就是一份代码跑在不同平台的同样的容器内,不用不同平台单独开发,节省成本。

但是跨平台方案也有缺点:

因为多了一层容器,所以性能相比直接调用系统api会有所下降

为了实现多平台的一致,需要提供一套统一的api,这套api有两个难题:

api怎么设计。要综合不同平台的能力,取一个合适的集合来实现。设计上有一定难度。node、deno、java都抽象了操作系统的能力,提供了各自的跨平台api

部分api很难做到多平台的一致性

当容器没有提供的能力需要扩展的时候比较麻烦,比如js引擎的bridge、jvm的jni、node的c++addon等都是为这个容器扩展能力的方式

前端领域的跨端方案

跨平台指的是跨操作系统,而跨端是指客户端。

客户端的特点就是有界面、有逻辑,所以包含逻辑跨端和渲染跨端。主要的客户端有web、安卓、ios、iot设备等。

现在主流的跨端方案有reactnative、weex、flutter、kraken以及各家自研的跨端引擎等。

reactnative

跨端包括逻辑跨端和渲染跨端,rn的逻辑跨端是基于js引擎,通过bridge注入一些设备能力的api,而渲染跨端则是使用安卓、ios实现react的virtualdom的渲染。

其中nativeapi和组件(灰色画出的部分)并没有做到双端一致,而且有的时候扩展图中灰色部分需要原生配合,混杂rn代码和自己扩展的代码导致代码比较难管理。最著名的事件就是airbnb从最大的reactnative支持者到弃用reactnative。

weex

weex也是类似的思路来实现跨端的,不过他对接的上层ui框架是vue,而且努力做到了双端的组件和api的一致性(虽然后续维护跟不上了)。架构和上图类似。

flutter

flutter是近些年流行的跨端方案,跨的端包括安卓、ios、web等。它最大的特点是渲染不是基于操作系统的组件,而是直接基于绘图库(skia)来绘制的,这样做到了渲染的跨端。逻辑的跨端也不是基于js引擎,而是自研的dartvm来跨端,通过dart语言来写逻辑,

kraken

跨端包括两部分,渲染跨端和逻辑跨端。有时候只需要渲染跨端、有时候只需要逻辑跨端,有的时候需要完整的跨端引擎,这3种情况都有各自的适用场景。

kraken就是一个跨端渲染引擎,基于flutter的绘图能力实现了css的渲染,实现了渲染的跨端。

自研渲染引擎

跨端引擎很依赖底层实现的组件和api,用开源方案也一样得扩展这部分,所以有一定规模的团队都会选择自研。

自研跨端引擎会和rn、weex不同:

渲染部分不需要实现virtualdom的渲染,而是直接对接domapi,上层应用基于这些domapi实现跨端渲染。这样理论上可以对接任意前端框架。

逻辑部分也是基于js引擎,通过binding直接注入一些c++实现的api,或者运行时通过bridge来注入一些安卓、ios实现的api。

自研跨端引擎的好处是组件和api可以自己扩展,更快的响应业务的需求。其中组件和api的双端一致性,以及统一的api的设计都是难点。

跨端的通用原理是什么

其实跨端和跨平台的思路类似,都是实现一个容器,给它提供统一的api,这套api由不同的平台各自实现,保证一致的功能。

具体一些的话,跨端分为渲染和逻辑跨端,有的时候只需要单独的渲染跨端方案(比如karen)和逻辑跨端方案,有的时候需要完整的跨端引擎。

weex、reactnative的渲染部分都是通过实现了virtualdom的渲染,用安卓、ios各自的渲染方式实现,逻辑部分使用js引擎,通过bridge注入一些安卓、ios的api。

flutter则是直接使用skia绘图库绘制,并且逻辑跨端使用dartvm。

但是不管具体实现怎样,思路都大同小异:跨端引擎需要实现一个渲染引擎、实现一个vm,基于这套架构实现各种组件和api,跨端容器上层对接一个ui框架,再上层的业务代码可以基于容器的api实现跨端的渲染和逻辑

webcontainer

这两天webcontainer比较火,其实也是一种跨平台技术,它是在浏览器里面实现的容器,通过wasm实现了node的api,这样在这个容器里面可以跑node代码。其实思路比较常见,但是是一个新场景。

浏览器容器之上又跑了个容器,容器套娃。

总结

我们聊了跨平台和跨端的区别,跨平台是指跨操作系统,而跨端则是指跨客户端。

跨平台技术聊了docker、浏览器、jvm、node、deno、electron、webcontainer等,他们都是跨平台(操作系统)的方案,跨平台有优点也有缺点,缺点就在于api的设计比较难,node、deno、java等都有自己的一层api设计;api一致性的保障也比较困难;其次就是扩展方式复杂一些(jvm的jni、node的c++addon等)。

跨端方案聊了reactnative、weex、flutter、kraken等,有的是绑定了react、vue等前端框架,直接从virtualdom渲染,有的是实现了domapi,可以对接任意前端框架。当然可以单独做渲染或逻辑跨端。渲染跨端或者用安卓、ios提供的方式,或者自己绘制,逻辑跨端或者用js引擎(可以对接前端框架)或者用dartvm。

希望这篇文章可以让你理解跨端和跨平台的容器的思路和优缺点,遇到一些新技术(比如webcontainer)也能快速的理解。




转载请注明:http://www.abachildren.com/sstx/3563.html