【必读】前端需要懂的 APP 容器原理

App 容器,简言之,App 承载某类应用(H5/RN/Weex/小程序/Flutter ...)的运行环境,可主动干预并进行功能扩展,达到丰富能力、优化性能、提升体验的目的,如页面数据预取(prefetch)缩短页面可用耗时、WebAR 将 AR 能力赋予 H5、Native 地图与 H5 复合渲染交互。


本篇主要就 H5 容器(WebView)相关建设进行概要展开。

我们先来做一个类比,通过 H5 的视角简要看一看 Android、iOS,进而更容易理解 WebView 容器建设机理。

本篇主要就 H5 容器(WebView)相关建设进行概要展开。

我们先来做一个类比,通过 H5 的视角简要看一看 Android、iOS,进而更容易理解 WebView 容器建设机理。

内容                                                     H5                                                    Android                                               iOS

窗口                                                    Window                                          PhoneWindow                                 UIWindow

页面控制                                               Html                                                    Activity                                  UIViewController

内容区                                                   body                                              contentView(DecorView)                          view

常规 UI(容器、文本、图片)            div、content、img                   View,TextView、ImageView            UIView、UILabel、UIImageView。

通过如上对比可知,Native 与 H5 有很多相通之处的,如:H5 是一个 html 创建一个页面;Android 是一个 Activity 创建一个页面;iOS 是 UIViewController 创建一个页面。不同处在于,

Native 本身有完善的页面栈管理机制,在同一个 runtime 环境里控制页面间转换;还可以管理多个窗口(Window),有多线程/进程(仅 Android)辅助合理使用资源保障主线程/进程性能,是 App 的体验。而 H5 本身受运行环境限制,只能在一个窗口里活动,目前缺少同一个 Runtime 内成熟的页面栈管理机制,当前 SPA 方式切换 view 来模拟“页面转场”,已是 WebApp 体验的一种较佳实现了。所以,在 App 里,H5 期望能借助更多的 Native 能力。

在 App 里,是通过 WebView 来访问 h5 页面的,先来看一下 WebView 的官方释义:

A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses theWebKit rendering engineto display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

其实,WebView 在 Android/iOS 两端的实现,都是继承自其 View/UIView 基类。对于 Native 原生来说,WebView 本身通过加载 h5 页面、通过 Chromium/WebKit 内核解析并进行 UI 合成,生成 view,Activity/UIViewController 实例的 View 通过 addView(Android)/addSubview(iOS)将 web view 添加进视图层,UI 合成,然后上屏展示。

我们知道,App 可以使用系统能力,但 WebView(类比浏览器)出于安全等考虑,默认并不提供。我们建设容器的一个主要目的是将 App 这些可用能力开放给容器。下面就谈一谈这部分能力是如何提供出来的,也就是下面要讲的桥通道相关建设。

网络优化

原生 Native 之所以体验平滑,有一关键点,是其页面依赖的静态资源大部分已打进安装包,跟随 App 的安装到了用户本地,节省了网络 IO 开销。顺着这个思路,在 5G 真正平民化之前,网络 IO 消耗,仍是提升性能的一个优化点,这块简要谈一下思路。

主要是两方面:

静态资源,html/js/css/图片/字体/视频等,通过离线化、预加载、懒加载、开启 WebView 缓存复用等进行文件获取前置备用或复用,当前用户访问页面加载资源时,容器拦截资源网络请求,命中离线或缓存的资源文件并使用。离线化与预加载可直接节省首次网络 IO 性能消耗,其他方式可以节省二次网络 IO 性能消耗。

离线化:即像 Native 一个打进 App 安装包内

预加载:App 启动后,在页面使用前,提前加载资源到用户本地备用

接口数据预取,选择合适的时机在用户访问页面前将接口数据获取到,当用户进入页面时,拦截接口网络请求直接命中本地缓存数据并使用。

这层优化,需要有配套的端远程控制机制与管理后台。合理设计总控机制,管控静态文件的发布、版本/patch 更新、下线等,以及接口数据预取的匹配规则、生命周期管理、静态/动态参数配置处理等。


WebAR

在说 WebAR 之前,先看一下 AR。简要讲:AR 是通过启动摄像头获取现实环境,以视频帧的形式将现实环境数据传输给 识别模块 与 绘制模块,识别模块将识别结果数据传递给绘制模块(根据业务配置的识别规则处理成对应的虚拟事物),绘制模块将 现实环境数据与识别结果数据处理后进行展现。


WebAR 是两个概念,是 Web + AR,在 Web 端提供 AR 能力。Web 自身,依靠 WebGL 实时图形渲染 与 WebRTC 实时视频流处理能力,能够实现 AR 体验。但受其运行环境标准不一、渲染性能差等因素影响,我们在容器侧进行了能力干预支持,以保障其功能与性能体验等。

在容器侧建设上,将 AR 能力集成到 App 上,再将 AR 能力提供给 WebView 使用(结合上面讲到的桥通道能力理解),以 H5 页的形式呈现。我们 Android 侧接入的是 UCWebView 提供的 AR 能力,使用 WebGL 渲染;iOS 是集成的 ARKit,通过全屏的 OpenGLView 上放置一个背景透明的 WebView 实现的混合渲染。

两端提供了配置识别模块能力支持。目前识别主要分为两类:一类基于 Maker 的识别(此类是常用的,识别标记图),另一类是基于位置的识别(通俗理解是通过手机传感器的方向和位置增强沉浸感,如位置远显示的内容较小,反之则大)。

当前小程序正如日中天,其有一项能力是很好的结合了 Native 与 H5,即“同层渲染”,下面我们也“纸上谈兵”一次。不过,我们也已有业务诉求,要做同层渲染的建设,将 Native 的 Video 等原生组件应用到 WebView 上满足业务体验需要。

同层渲染

这里讲的同层渲染,是将 Native view 合成到 WebView 上,可以通过 CSS 控制 Native View 在页面的样式。

以下介绍的两端方案,是基于目前笔者了解到的实现方案里最佳的。

Android

需要基于 Chromium 内核扩展自研的 WebView。Chromium 支持 WebPlugin 机制,用来识别解析 dom 标签。其思路:

html 里创建 dom 节点,指定组件类型,供容器识别处理

Chromium 创建 WebPlugin 实例,并生成 RenderLayer,其作用是创建独立的层并返回相应的画布供视图绘制使用

Android 根据识别的 组件类型 ,初始化一个对应的原生组件

Android 将原生组件的视图绘制 到 RenderLayer 所绑定的 SurfaceTexture 上(将 Android 的 UI Toolkit 的视图的数据送到 Texture 供 openGL 绘制使用)

Chromium 将此 RenderLayer 与 Web 页面的 View 进行合成渲染

iOS

基于 WKWebView,WK 在内部采用的是分层的方式进行渲染,一般会将多个 dom 节点,合并到一个层上进行渲染。因此,dom 节点和层之间不存在一一对应关系。但是,若将一个 dom 节点的 CSS 属性设置为 “overflow: scroll” 后,WKWebView 便会为其生成一个 WKChildScrollView,且 WebKit 内核已经处理了 WKChildScrollView 与其他 dom 节点之间的层级关系,这时 dom 节点就和层之间有一一对应关系了。所以,同层渲染可基于 WKChildScrollView 实现:

1.html 里创建 din 节点并设置其 CSS 属性为 overflow: scroll,指定组件类型,供容器识别处理

2.iOS 查找到该 dom 节点对应的原生 WKChildScrollView 组件

3.iOS 根据识别的 组件类型 ,初始化一个对应的原生组件

4.iOS 将原生组件挂载到该 WKChildScrollView 节点上作为其子 view,这样原生组件就被插入到了 webView 上

5.WebKit 完成渲染

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356