H5即开并行加载方案,从不足到精进,有哪些演进之路?

摘要:并行加载是 H5 即开 SDK 的加速技术,通过 native 层在用户打开页面时并行请求关键资源(如 index.html 和 CSR 模式 API),利用 webview 初始化时间窗口提前发起请求,减少加载耗时。其核心挑战是解决 we
作者: vivo 互联网客户端团队- Chen Long 并行加载是 H5 即开 SDK 的加速技术,通过 native 层在用户打开页面时并行请求关键资源(如 index.html 和 CSR 模式 API),利用 webview 初始化时间窗口提前发起请求,减少加载耗时。其核心挑战是解决 webview 与并行任务间的资源交接问题。 1分钟看图掌握核心观点👇 一、并行加载能力核心解析 1.1 什么是并行加载 并行加载是H5即开SDK提供的一项加速能力,核心逻辑是:在用户打开页面时,通过native层并行请求关键资源,减少页面加载耗时。其本质是利用webview及native页面初始化的时间窗口,提前发起资源请求,实现"时间复用"。 1.2 核心加载资源 并行加载的关键资源包含两类: H5页面首帧渲染依赖的index.html(首帧资源,加载时机极早)。 CSR模式下页面依赖的API接口(通常在首帧渲染后调用,加载时机较晚)。 1.3 工作流程示意图 即开SDK在流程中主要完成两件事: 用户打开URL时,并行请求H5依赖的API接口或index.html文件。 拦截webview请求,将并行加载的缓存数据导流给webview,实现加速。 二、并行加载的核心挑战:资源交接场景 并行加载的核心问题是如何在webview需要资源时,将并行请求的资源无缝交接。根据资源状态可分为三类场景: 下面我们针对三个场景分别看处理方案 2.1 场景一:网络数据尚未响应,webview开始需要资源 解决方案一 忽略网络数据,webview自己加载资源。 矛盾点: 如果是因为服务器压力大,网络环境差导致的响应慢,webview自己去加载也会遇到同样的问题,而且直接放弃已并行加载的任务,等于是浪费了已经处于建联中,可能已经完成了一部分等待的时间。 解决方案二 webview等待网络资源加载成功后,再使用加载成功的资源。 矛盾点: 让webview的资源获取线程等待并行任务响应并返回,那么等多久,如果时间太久怎么办,需要设置超时时间,如何等待,并且在等待的过程中还要监控并行任务是否已经返回。 2.2 场景二:网络数据已响应,webview开始需要资源 场景二需要考虑两种情况 情况一 在webvie需要数据的时候,网络数据流刚好完成建联,webview可以直接使用网络数据流加载。 情况二 网络数据流建联的时候,webview还未开始需要使用数据,并行任务有时间将网络数据流读取到缓冲区中,webview在需要数据的时候,可以读取缓冲区的数据。 矛盾点: 大家知道网络数据读取是有受限于网络环境影响的,预先进行网络的数据读取,再交接给webview,肯定能更大程度上降低读取耗时,但是问题又来了,如果并行任务在读取的过程中,还没有读完,webview就来要数据怎么办,让webview等待吗?如果等待,等待多久?如果不等待,又如何将已读取在缓冲区中的数据和未读取的网络流数据一起交给webview呢。 2.3 场景三:网络数据返回错误,webview开始需要资源 解决方案 并行任务已失败,直接废弃并行任务,让webview自己加载资源。 三、早期方案设计与局限 在最开始,我们希望并行任务设计的足够简单,基于以上所有场景下的理解,权衡开发难度,我们设计了第一个方案。 首先我们希望避开场景二中,网络数据流已建联,网络线程正在读取网络流到缓冲区,读到一半webview来取数据的场景,因为我们觉得这种场景较为复杂,如果返回混合流,可能会出现控制不好的情况,而且整个过程中,两条线程参与的生产者和消费者,存在一个中间态,也就是生产者生产到一半时,消费者过来要消费数据,生产者要立刻停止生产,并把未成品交给消费者,这显然比常规的生产者消费者模式更加复杂,于是我们决定用更简单的方法来处理,方案就是把这个较为复杂的生产者消费者,变回简单的典型生产者消费者,消费者不能打断生产者的生产过程,而是等待生产完成,避免中间态下的复杂处理,虽然做了妥协,但是我们依然希望有较好的性能,所以我们将index.html任务和CSR模式下的API任务分为两个不同的方式来进行处理。 3.1 index.html首帧资源处理 index.html,这是webview完成初始化后第一个要加载的资源,俗称首帧资源。因此index.html的使用时机可以说是非常的靠前,在并行加载任务中,它的可用并行加载时间也大致在100ms左右,我们认为在这个时间内,并行任务大概率可以完成建联,但是可能没有时间再完成数据流的读取。 因此,我们使用了stream对象来保存网络数据流。
阅读全文