某天夜黑风高,突然收到一个任务:提升移动端应用中H5页面的加载速度,因为目前加载速度太慢,甚至超过10秒。这对于移动应用来说是一个严重的问题,因此我开始进行调研,寻找解决方案并最终将其成功应用到线上。接下来,我将分享一下我的实施经验以及在过程中遇到的一些坑点
在项目中,经过一番战斗终于发现H5页面加载速度较慢主要集中在以下几个方面:
- HTML下载延迟: 可能由于CDN节点分配问题或HTML响应时间过长导致HTML文件下载速度较慢。
- 媒体资源(图片和音频)下载延迟: 图片和音频等媒体资源的下载速度也是一个瓶颈。
- 渲染效率问题: 在前端同学的努力下,我们已经对页面渲染进行了优化。这包括减少DOM操作、合理使用CSS和JavaScript,以及避免不必要的重绘。前端同学在这方面的工作使得页面的渲染速度得到了提升,进一步改善了用户体验。
通过对以上问题的分析和优化,我们决定做缓存,主要方案如下:
在制定优化方案之前,强烈建议同事们保持大胆创新的心态,但同时要保持细致入微的注意力。在实施新功能或变更时,务必谨慎操作,采用白名单和开关机制,并通过服务器进行逐步放开。我深信,你们将面对与他人不同的挑战和潜在崩溃。勇于尝试是重要的,但要避免盲目大胆而忽略了谨慎。在这个过程中,大胆可以,但不傻大胆
-
提前做
a. 提前加载web内核,放入缓存池,每次取web,如下图
这个时候要注意了,注意了,每次重置webview一定要加载一个空白页面,才算真正保留web内核以及重新loadweb
-
减少做
通过本地缓存webview中的html、js、css、png、jpg等资源、每次启动可以从本地拿资源不在通过网络下载提升速度,那么怎么获取到网页加载所需要的资源呢有两种方案。
方案1:
每次启动从服务器获取zip包 每个html对应一个map包含所需要的所有资源,此方案需要牵涉到服务器添加、前端同学去做梳理、每次有更新要同步到服务器或者后台、成本比较大、不灵活~~~~~此方案在此次不作为最优方案
方案2:
监控wkwebview的所有网络请求、目前有两种方案可以实现对web的网络的接管
接管webview网络请求方案对比
- NSURLProtocol registerClass
- 通过WKWebViewConfiguration提供的setURLSchemeHandler注册scheme方式实现
安全性:
NSURLProtocol 入侵性比较强、所有webview的请求都会被拦截、风险比较大、甚至一些第三方请求也会被拦截
WKURLSchemeHandler通过webview的configuration注册进入,可以控制单个webview、更好掌控
扩展性:
NSURLProtocol在网络发起的阶段进行拦截、缓存的资源无法拦截、不好掌控所有请求
WKURLSchemeHandler时机比较靠前,比较好掌控,但是不想拦截的请求目前没有找到办法转交给webview、这点比较鸡肋
从安全性、扩展性来说 WKURLSchemeHandler 是我们目前比较好的选择
执行方案
- 启动白名单机制、出现bug、或者崩溃服务器可以随时关闭整个方案、走原生方案
- 逐步覆盖、目前只会缓存白名单里的页面、稳定以后可以考虑全量放开
方案流程图
缓存数据策略:
使用YYDiskCache 内部采用LRU策略,最大磁盘缓存30M
数据打点:
web加载完成上报参数(url duration 是否是白名单 是否成功)
webView知识整理
webview的进程:(稳定性、安全性、流畅性)
- 主进程:负责管理用户界面,响应用户交互以及处理其他应用程序逻辑,在主进程中创建和管理 wkwebview实例,并且与其交互
- Webcontent process: 将HTML、CSS、JS转为用户可以与之交互的网页,处理渲染操作,一般每次创建一个webview都会为之创建一个渲染进程
- Network process: 负责发出web网络请求所有网页共享这一进程,通过NSURLSession发起管理网络,并且多个webview共享此进程
- Storage process:用于数据库和服务器的存储
webview整个加载过程分为三部分:初始化->网络加载->渲染
初始化:
- wkwebview初始化,系统会加载和初始化webkit框架,然后根据设备的操作系统选择合适版本的渲染引擎
- 为此web对象创建一个渲染进程并且建议进程通信机制
- 配置渲染选项,例如是否自动缩放,是否允许内联媒体播放器
- 给渲染进程注册回调
Todo: 不是alloc init初始化就完成了 在loadrequest调用刚开始才会去处理进程以及开启IPC通信、添加proxy
建立链接和网络加载
- 构建请求、查找缓存
- dns解析
- 建立TCP连接、,如果是HTTPS还要建立TLS连接
- 发送HTTP请求,请求HTML
todo:iOS14以及以前的版本,默认情况可以并行下载6个资源 并行下载的资源数量是由 WKWebView
内部进行管理的,开发者无法直接控制或配置该数量。它是根据系统和设备的条件自动调整的,以平衡加载性能和资源管理
渲染
- Network process接收到response响应头之后,开始将数据转发主进程,主进程收到后发送提交导航消息给渲染进程,开始和网络进程建立数据"管道"接收HTML数据, 接收完成后渲染进程返回确认提交给浏览进程(didcommit),
- 解析HTML数据、开始加载js、css以及构建DOM树、进行样式计算将css转成浏览器可以理解的结构、标准化转换样式、计算DOM节点样式、布局、构建布局树、进行布局计算、绘制
iOS WKWebView代理回调和进程之间的关系
- 调用webview loadRequest,触发网络进程创建,主进程通过进程通信将request发给networkprocess进行预加载,建立TCP,同时为WK配置参数,建立IPC通信
- 将request发给content process进程,webcontent创建加载器加载网络请求(调用decidePolicyForNavigationAction),取消上个页面的请求,找到当前页面绑定号的netwrok进程进行网络下载调用didstart
- Network process接收到响应数据,开始解析响应头,将数据转发给主进程,然后发起导航消息到content 进程,content进程开始准备接收HTML数据
- 接收HTML完毕,content process像主进程确认是否响应(decidePolicyForNavigationResponse)如果允许调用(didcommit) 开始解析HTML 边下载js css 图片等 边渲染
- 页面展示调用didFinish
参考文献
极客时间 <<浏览器工作原理与实践 >> 这本书 可以找找免费课程