写给前端的跨平台方案、跨端引擎的本质
共 3855字,需浏览 8分钟
· 2021-05-29
那么多跨端方案,他们有没有通用的思路?我们能不能从这么多方案中找出本质的原理?
本文会尝试探究探究以下问题:
什么是跨平台 有哪些方案是跨平台的 跨端和跨平台的区别是什么 前端领域有哪些跨端方案 跨平台、跨端的通用原理是什么
什么是跨平台
我们知道,cpu 有不同的架构和指令集,上层也有不同的操作系统,一个系统的可执行文件在另一个系统上就是不可执行的,比如 windows 的 exe 文件在 mac 上就不能直接执行。不同的系统就是不同的运行平台。可执行文件是不跨平台的。
不同平台提供的 api 不同,所以代码逻辑可能也不同,需要不同平台单独维护代码。这样就带来了几个问题:
多平台各自开发,怎么保证功能是一致的 多平台各自开发,那是不是得各自测试,开发和测试的人力都是多份的
所以出现了跨平台的一些技术,目标是一份代码跑在任意平台。
我们先来看一些各领域的跨平台方案:
浏览器
操作系统不同,浏览器上跑的网页的代码确实同一份。浏览器就是一种历史悠久的跨平台方案。
网页跨平台不意味着浏览器也是跨平台的,浏览器的可执行文件还是每个平台单独开发和编译的,但是他们支持的网页解析逻辑一样,这样上面跑的网页就是跨平台的。
浏览器提供了一个容器,屏蔽了底层差异,提供了统一的 api(dom api),这样就可以实现同一份代码跑在不同平台的统一的容器里。这个容器叫做浏览器引擎,由 js 引擎、渲染引擎等构成。
![](https://filescdn.proginn.com/36b1815d2cb5af479067f13f9e76bdda/b34798c9b02d3d27b17ebb0636075d87.webp)
docker
docker 是一种虚拟化技术,可以在操作系统之上加一个虚拟层,在这层之上划分一到多个容器,容器里再去跑系统、app,这样可以实现硬件和软件的分离,动态分配硬件资源给容器,并且方便 app 运行环境的整体迁移(保存成镜像)。
![](https://filescdn.proginn.com/60814965390029192527fa37a32f9bd5/ca64e352d9d764a21ff35fbdfcf92dde.webp)
docker 很明显也是一种跨平台技术,同一个镜像可以跑在任何操作系统的 docker 上。只要不同操作系统实现同样的容器即可。
jvm
java 是一门编译 + 解释的语言,java 源码编译成字节码,然后字节码直接在 vm 上解释执行。
java 为什么这么火呢?主要是因为跨平台。
c、c++ 这种语言写的代码需要编译成不同操作系统上的可执行文件来跑,而且每个平台的代码可能还不一样,需要写多份。
java 因为提供了 jvm 容器,只要把源码编译成 jvm 能解释的字节码就行了,而且 jdk 提供了统一的 api,分别由不同操作系统的底层 api 来实现,这样对于 java 代码来说,不同操作系统的代码是一致的。
![](https://filescdn.proginn.com/229247b40dbad5fb8b5a8c93c34c234d/61596c0e1410702f54ab7b624e3d2e95.webp)
jvm 也是通过容器的技术实现了一份代码跑在多个平台,而且 jre 提供了统一的 api,屏蔽掉了底层的差异。
node、deno
node 和 deno 也是跨平台的技术,通过提供一套一致的 api,让其上的 js 代码可以跨平台。这些 api 也是不同平台各自实现的。
![](https://filescdn.proginn.com/4381fc6617280f15cd5477e31920e624/feb412b7f5c88470df23762ec8005bc0.webp)
electron
electron 内置了 chromium,并为其注入了 node 的 api 和一些 GUI 相关的 api,是基于两大跨平台技术综合而成的跨平台方案。基于这些方案的组合使得 electron 支持用前端技术开发桌面端。
![](https://filescdn.proginn.com/cd5c6d20246404ef056394b06e51e0e7/4327fb6ea9f7b34b25808cc411ff04ae.webp)
跨平台方案的优缺点
跨平台方案的优点很明显,就是一份代码跑在不同平台的同样的容器内,不用不同平台单独开发,节省成本。
但是跨平台方案也有缺点:
因为多了一层容器,所以性能相比直接调用系统 api 会有所下降
为了实现多平台的一致,需要提供一套统一的 api,这套 api 有两个难题:
api 怎么设计。要综合不同平台的能力,取一个合适的集合来实现。设计上有一定难度。node、deno、java 都抽象了操作系统的能力,提供了各自的跨平台 api
部分 api 很难做到多平台的一致性
当容器没有提供的能力需要扩展的时候比较麻烦,比如 js 引擎的 bridge、 jvm 的 jni、node 的 c++ addon 等都是为这个容器扩展能力的方式
前端领域的跨端方案
跨平台指的是跨操作系统,而跨端是指客户端。
客户端的特点就是有界面、有逻辑,所以包含逻辑跨端和渲染跨端。主要的客户端有 web、安卓、ios、iot 设备等。
现在主流的跨端方案有 react native、weex、flutter、kraken 以及各家自研的跨端引擎等。
react native
跨端包括逻辑跨端和渲染跨端,rn 的逻辑跨端是基于 js 引擎,通过 bridge 注入一些设备能力的 api,而渲染跨端则是使用安卓、ios 实现 react 的 virtual dom 的渲染。
![](https://filescdn.proginn.com/32830aaa8ded4cf511e8f8cf7cb75fcc/26701dfdea65908c6f140984780a66cd.webp)
其中 native api 和组件(灰色画出的部分)并没有做到双端一致,而且有的时候扩展图中灰色部分需要原生配合,混杂 rn 代码和自己扩展的代码导致代码比较难管理。最著名的事件就是 airbnb 从最大的 react native 支持者到弃用 react native。
weex
weex 也是类似的思路来实现跨端的,不过他对接的上层 ui 框架是 vue,而且努力做到了双端的组件 和 api 的一致性(虽然后续维护跟不上了)。架构和上图类似。
flutter
flutter 是近些年流行的跨端方案,跨的端包括安卓、ios、web 等。它最大的特点是渲染不是基于操作系统的组件,而是直接基于绘图库(skia)来绘制的,这样做到了渲染的跨端。逻辑的跨端也不是基于 js 引擎,而是自研的 dart vm 来跨端,通过 dart 语言来写逻辑,
![](https://filescdn.proginn.com/3ffe2a3c343cebc5278e1ee3fef4b374/d5342da3dc005216c8474f028ce9b4a7.webp)
kraken
跨端包括两部分,渲染跨端和逻辑跨端。有时候只需要渲染跨端、有时候只需要逻辑跨端,有的时候需要完整的跨端引擎,这 3 种情况都有各自的适用场景。
kraken 就是一个跨端渲染引擎,基于 flutter 的绘图能力实现了 css 的渲染,实现了渲染的跨端。
![](https://filescdn.proginn.com/86e16cc47eba60661e5e02970ad0fedf/4f1c32d00e7db632f998b9c09891dc93.webp)
自研渲染引擎
跨端引擎很依赖底层实现的组件和 api,用开源方案也一样得扩展这部分,所以有一定规模的团队都会选择自研。
自研跨端引擎会和 rn、weex 不同:
渲染部分不需要实现 virtual dom 的渲染,而是直接对接 dom api,上层应用基于这些 dom api 实现跨端渲染。这样理论上可以对接任意前端框架。
逻辑部分也是基于 js 引擎,通过 binding 直接注入一些 c++ 实现的 api,或者运行时通过 bridge 来注入一些安卓、ios 实现的 api。
![](https://filescdn.proginn.com/8f8794b36d678394fa5f0e82110792ac/af14df21e56faee0600fbd5b8b536f79.webp)
自研跨端引擎的好处是组件和 api 可以自己扩展,更快的响应业务的需求。其中组件和 api 的双端一致性,以及统一的 api 的设计都是难点。
跨端的通用原理是什么
其实跨端和跨平台的思路类似,都是实现一个容器,给它提供统一的 api,这套 api 由不同的平台各自实现,保证一致的功能。
具体一些的话,跨端分为渲染和逻辑跨端,有的时候只需要单独的渲染跨端方案(比如 karen)和逻辑跨端方案,有的时候需要完整的跨端引擎。
weex、react native 的渲染部分都是通过实现了 virtual dom 的渲染,用安卓、ios 各自的渲染方式实现,逻辑部分使用 js 引擎,通过 bridge 注入一些安卓、ios 的 api。
flutter 则是直接使用 skia 绘图库绘制,并且逻辑跨端使用 dart vm。
但是不管具体实现怎样,思路都大同小异:跨端引擎需要实现一个渲染引擎、实现一个 vm,基于这套架构实现各种组件和 api,跨端容器上层对接一个 ui 框架,再上层的业务代码可以基于容器的 api 实现跨端的渲染和逻辑
web container
这两天 web container 比较火,其实也是一种跨平台技术,它是在浏览器里面实现的容器,通过 wasm 实现了 node 的 api,这样在这个容器里面可以跑 node 代码。其实思路比较常见,但是是一个新场景。
![](https://filescdn.proginn.com/e67df7f37a0035c2623ce296b33ab044/87241a867fb67e0160951e37161a5d0e.webp)
浏览器容器之上又跑了个容器,容器套娃。
总结
我们聊了跨平台和跨端的区别,跨平台是指跨操作系统,而跨端则是指跨客户端。
跨平台技术聊了 docker、浏览器、jvm、node、deno、electron、web container 等,他们都是跨平台(操作系统)的方案,跨平台有优点也有缺点,缺点就在于 api 的设计比较难,node、deno、java 等都有自己的一层 api 设计;api 一致性的保障也比较困难;其次就是扩展方式复杂一些(jvm 的 jni、node 的 c++ addon 等)。
跨端方案聊了 react native、weex、flutter、kraken 等,有的是绑定了 react、vue 等前端框架,直接从 virtual dom 渲染,有的是实现了 dom api,可以对接任意前端框架。当然可以单独做渲染或逻辑跨端。渲染跨端或者用安卓、ios 提供的方式,或者自己绘制,逻辑跨端或者用 js 引擎(可以对接前端框架)或者用 dart vm。
希望这篇文章可以让你理解跨端和跨平台的容器的思路和优缺点,遇到一些新技术(比如 web container)也能快速的理解。