一、概述

在移动互联网时代,应用的页面渲染速度对于用户体验至关重要。相对于原生页面,Web页面的性能存在多方面的技术挑战。本文以HarmonyOS的ArkWeb组件为基础,介绍了Web页面加载中的影响因素以及对应的优化方案。

二、Web页面加载性能优化指导

(一)Web页面加载流程

Web页面加载包含网络连接、资源下载、DOM解析、JavaScript代码编译执行和渲染等关键环节,本文主要针对网络连接、资源下载和完整页面渲染这些关键节点的耗时进行优化。

  • 预启动Web渲染进程:预启动Web渲染进程指用户可以在业务需要的Web页面启动前,加载一个空白的Web组件,在至少一个Web组件存活时,Web渲染进程进程会一直存在,节省了用户后续启动Web组件拉起渲染进程的时间,加快页面加载速度。

  • 预解析:预解析指预先对DNS进行解析,可以节省DNS解析的时间,从而优化Web的加载耗时。

  • 预连接:预连接包含预解析的步骤,可以在用户请求页面之前提前进行DNS解析和socket连接建立,这样当用户真正请求页面时,服务器和浏览器之间已经建立好了连接,可以直接传输数据,减少了网络延迟,提升了页面加载速度。

  • 预下载:预下载指在页面加载之前提前下载所需的资源,以避免在页面加载过程中资源下载导致的阻塞和耗时。通过预下载,可以在浏览器加载页面时,提前获取到所需的资源如图片、CSS文件、JavaScript文件等。通过提前下载这些资源,可以避免在页面加载时因为资源未加载完成而导致页面渲染延迟的情况发生。通过合理地使用预下载技术,用户在访问页面时可以更快地看到页面内容,提高整体性能,提升用户体验。

  • 预渲染:预渲染指在后台对需要加载的页面进行预先渲染,提前完成整个页面加载的流程。当用户需要访问该页面时,可以直接切换至前台展示,实现页面“秒开”的效果。预渲染要求在进行DOM解析、JavaScript执行和页面渲染之前,已经完成了所需资源的下载工作,否则可能会导致页面内容不完整或者渲染错误的情况。通过预渲染,可以显著减少用户等待页面加载的时间,特别是对于一些需要加载大量资源或者有复杂交互的页面。

  • 预取POST:预取POST指当即将加载的Web页面中存在POST请求且POST请求耗时较长时,可对POST请求进行预获取,消除等待POST请求数据下载完成的耗时,当用户真正发起POST请求时,进行拦截替换,加快页面加载速度,提高用户体验。

  • 预编译JavaScript生成字节码缓存(Code Cache):该方案会将使用到的JavaScript文件编译成字节码并缓存到本地,在页面首次加载时节省编译时间。

  • 资源拦截替换的JavaScript生成字节码缓存(Code Cache):该方案会将资源拦截替换场景下的JavaScript文件编译成字节码并缓存到本地,节省在页面非首次加载时的编译时间。

  • 离线资源免拦截注入:在页面加载之前,离线资源免拦截注入会将需要使用的图片、样式表和脚本资源注入到内存缓存中,节省页面首次加载时的网络请求时间。

  • 资源拦截替换加速:在原本的资源拦截替换接口基础上,资源拦截替换加速支持了ArrayBuffer格式的入参,开发者无需在应用侧进行ArrayBuffer到String格式的转换,可直接使用ArrayBuffer格式的数据进行拦截替换。
     

    输入图片说明


    由于所有的关键点都是建立在预处理的思路上,因此如果用户实际并未打开预处理的Web页面,将会造成额外的资源消耗。各优化方法具体的效果、代价和适用场景的对比如下表所示。

    优化方法效果(优化数据仅供参考)适配难度影响适用场景
    预启动Web渲染进程消除拉起Web渲染进程的耗时,约140ms。额外的内存、算力。高概率被使用的Web页面。
    预解析消除用户真正启动的Web网页域名解析的耗时,约66ms。可能存在提前解析了用户未启动的Web网页域名。中高概率被使用的Web页面。
    预连接消除用户真正启动的Web网页域名解析、网络连接耗时,约80ms。可能存在提前连接了用户未启动Web网页资源。中高概率被使用的Web页面。
    预下载消除网络GET请求下载带来的耗时及阻塞DOM解析、JavaScript执行的耗时,约641ms。额外的网络连接、下载、存储资源。高概率被使用的Web页面。
    预渲染能实现页面“秒开”效果,将页面加载时延降到最低,约486ms。额外的网络连接、下载、存储和渲染消耗。超高概率被使用的Web页面。
    预取POST消除网络POST请求下载带来的耗时及阻塞DOM解析、JavaScript执行的耗时,约313ms。额外的网络连接、下载、存储资源。高概率被使用的Web页面。
    预编译JavaScript生成字节码缓存消除JavaScript编译的耗时,优化数据根据JS资源大小而定,5.76Mb资源预编译时约有2915ms收益。额外的存储资源。加载HTTP/HTTPS协议JavaScript的Web页面,在第一及第二次优化加载性能。
    资源拦截替换的JavaScript生成字节码缓存消除JavaScript编译的耗时,优化数据根据JS资源大小而定,2.4Mb资源拦截替换时约有67ms收益。额外的存储资源。加载自定义协议JavaScript的Web页面,在第三次及之后的时机优化加载性能。
    离线资源免拦截注入消除资源加载到内存的耗时,优化数据根据资源大小而定,25Mb资源注入时约有1240ms收益。额外的存储资源。高概率被使用的资源。
    资源拦截替换加速节省了转换时间,同时对ArrayBuffer格式的数据传输方式进行了优化,优化数据根据资源大小而定,10Kb资源拦截替换时约有20ms收益。-ArrayBuffer格式的数据传输。

(二)预启动Web渲染进程

原理介绍

此方案适用于Web页面启动场景。开发者需额外创建一个空白的ArkWeb组件,它虽不显示给用户,但会提前拉起渲染进程,且该进程在Web组件全部销毁前与应用侧全局共用,可节省后续组件加载时启动渲染进程的时间。不过,创建此组件会消耗约200Mb内存和算力。

建议在Web页面启动前(如应用冷启动或广告阶段)执行该方案,若冷启动无法进行,可在空闲时间启动。

输入图片说明

(三)预解析和预连接优化

原理介绍 如下图所示,在应用启动和UIAbility的onCreate生命周期后,Web组件才能进行初始化和运行。在ArkWeb组件运行阶段,会经过onAppear、load、onPageBegin、onPageEnd步骤。预解析、预连接优化适用于Web页面启动和跳转场景,例如,应用启动时需要加载Web首页。当开发者已经创建一个ArkWeb组件的实例后,可以选择不同时机对当前ArkWeb组件设置URL并进行预解析、预连接:

  • 如下图中a节点所示,如果是应用首页,推荐在ArkWeb组件初始化创建后设置首页的URL,进行预解析、预连接;
  • 如下图中b节点所示,如果是应用内页面,推荐ArkWeb组件onAppear阶段设置当前页面的URL,进行预解析、预连接;
  • 如下图中c节点所示,当前页面完成加载后,可以设置用户下一步可能点击页面的URL,进行预解析、预连接,推荐在onPageEnd及后续时机进行。

    输入图片说明

(四)预下载优化

原理介绍

适用于Web页面启动和跳转场景。在ArkWeb组件运行的onPageEnd阶段,可设置URL提前下载页面所需资源,能消除资源下载耗时及对DOM解析和JS代码编译执行的阻塞耗时,但会消耗额外流量和内存,适合高频页面。预下载行为包括连接和资源下载,耗时可能达700ms以上,预下载完成后当前组件连接关闭,如需下一个页面预连接需显式调用接口。

输入图片说明

(五)预渲染优化

原理介绍

预渲染优化适用于Web页面启动和跳转场景,例如,进入首页后,跳转到其他子页。与预连接、预下载不同的是,预渲染需要开发者额外创建一个新的ArkWeb组件,并在后台对其进行预渲染,此时该组件并不会立刻挂载到组件树上,即不会对用户呈现(组件状态为Hidden和InActive),开发者可以在后续使用中按需动态挂载。

具体原理如下图所示,首先需要定义一个自定义组件封装ArkWeb组件,该ArkWeb组件被离线创建,被包含在一个无状态的节点NodeContainer中,并与相应的NodeController绑定。该ArkWeb组件在后台完成预渲染后,在需要展示该ArkWeb组件时,再通过NodeController将其挂载到ViewTree的NodeContainer中,即通过NodeController绑定到对应的NodeContainer组件。预渲染通用实现的步骤如下:

  1. 创建自定义ArkWeb组件:开发者需要根据实际场景创建封装一个自定义的ArkWeb组件,该ArkWeb组件被离线创建。
  2. 创建并绑定NodeController:实现NodeController接口,用于自定义节点的创建、显示、更新等操作的管理。并将对应的NodeController对象放入到容器中,等待调用。
  3. 绑定NodeContainer组件:将NodeContainer与NodeController进行绑定,实现动态组件页面显示。
  • 输入图片说明

(六)预取POST请求优化

原理介绍

预取POST请求适用于Web页面启动和跳转场景,当即将加载的Web页面中存在POST请求且POST请求耗时较长时,会导致页面加载时间增加,可以选择不同时机对POST请求进行预获取,消除等待POST请求数据下载完成的耗时,具体有以下两种场景可供参考:

  1. 如果是应用首页,推荐在ArkWeb组件创建后或者提前初始化Web内核后,对首页的POST请求进行预取,如XComponent.onCreate()、自定义组件的生命周期函数aboutToAppear()。
  2. 当前页面完成加载后,可以对用户下一步可能点击页面的POST请求进行预取,推荐在Web组件的生命周期函数onPageEnd()及后续时机进行。

(七)预编译JavaScript生成字节码缓存(Code Cache)

原理介绍

预编译JavaScript生成字节码缓存适用于在页面加载之前提前将即将使用到的JavaScript文件编译成字节码并缓存到本地,在页面首次加载时节省编译时间。

开发者需要创建一个无需渲染的离线Web组件,用于进行预编译,在预编译结束后使用其他Web组件加载对应的业务网页。

(八)资源拦截替换的JavaScript生成字节码缓存(Code Cache)

原理介绍

对资源拦截替换场景下的JavaScript文件进行编译和缓存,节省非首次加载时的编译时间。
JS资源编译执行流程
 

输入图片说明

 资源拦截替换后JS资源编译执行流程
 

输入图片说明

 Web组件默认支持HTTP协议的JavaScript生成字节码缓存,也支持自定义协议的JavaScript生成字节码缓存,具体步骤如下:

  1. 开发者首先需要在Web组件运行前,向Web组件注册自定义协议。

  2. 其次需要拦截自定义协议的JavaScript,设置ResponseData和ResponseDataID。

(九)离线资源免拦截注入

原理介绍

在页面加载前,将图片、样式表和脚本资源注入内存缓存,节省首次加载的网络请求时间。

说明

  1. 开发者需创建一个无需渲染的离线Web组件,用于将资源注入到内存缓存中,使用其他Web组件加载对应的业务网页。
  2. 仅使用HTTP或HTTPS协议请求的资源可被注入进内存缓存。
  3. 内存缓存中的资源由内核自动管理,当注入的资源过多导致内存压力过大,内核自动释放未使用的资源,应避免注入大量资源到内存缓存中。
  4. 正常情况下,资源的有效期由提供的Cache-Control或Expires响应头控制其有效期,默认的有效期为86400秒,即1天。
  5. 资源的MIMEType通过提供的参数中的Content-Type响应头配置,Content-Type需符合标准,否则无法正常使用,MODULE_JS必须提供有效的MIMEType,其他类型可不提供。
  6. 仅支持通过HTML中的标签加载。
  7. 如果业务网页中的script标签使用了crossorigin属性,则必须在接口的responseHeaders参数中设置Cross-Origin响应头的值为anoymous或use-credentials。
  8. 当调用webview.WebviewController.SetRenderProcessMode(web_webview.RenderProcessMode.MULTIPLE)接口后,应用会启动多渲染进程模式,此方案在此场景下不会生效。
  9. 单次调用最大支持注入30个资源,单个资源最大支持10Mb。

(十)资源拦截替换加速

原理介绍

资源拦截替换加速在原本的资源拦截替换接口基础上新增支持了ArrayBuffer格式的入参,开发者无需在应用侧进行ArrayBuffer到String格式的转换,可直接使用ArrayBuffer格式的数据进行拦截替换。

三、总结

本文深入探讨了Web页面加载的原理和优化方法,为开发者提供了重要的指导和思路。在当今互联网时代,用户对网页加载速度和体验要求越来越高,因此页面加载优化成为开发者必须重视的一环。通过理解Web页面加载的原理,开发者可以更好地处理页面加载与优化的相关问题,提升应用的整体质量。

文中提供了预连接、预下载、预渲染、预取POST、预编译等多种常见的优化方法,指导开发者优化Web页面的加载速度。这些方法可以有效提高应用流畅度、提升用户体验。

综上所述,Web页面加载优化对于提升用户体验、提高网站性能、增加页面浏览量和提高转化率具有重要意义。开发者应该重视页面加载优化,不断探索和实践各种优化方法,以提升用户体验,实现商业目标。通过文章介绍的几种优化方法,开发者可以改善页面加载速度,提升用户体验,增加页面浏览量,提高应用的活跃度和用户粘性。只有不断优化页面加载速度,才能更好地满足用户需求,提升应用价值。

最佳实践

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐