前言#
市面上业务复杂 App中近半数业务页面使用H5 页面承载,H5的优势很明显,跨平台、迭代快、开发体验好,H5的劣势同样明显,加载慢,用户体验差,为了提高页面加载速度和成功率,我们在app H5 部分业务加载 采用了离线包方式,如果有业务功能有变更,就通过我们的无线发布系统,将新的业务离线包更新到App 中,从而做到随时发布,动态更新,页面秒开,无须app 改动。
背景#
目前优化Web页面体验方案比较多,有Flutter、React Native、小程序、离线包,其中离线包技术对现有H5页面改造成本小,技术最为成熟和稳定。它具有快速迭代发布的天然优势。
离线包加载方案#
目前 成熟的方案离线包加载有本地服务和 本地资源加载 请求拦截,下面是相关方案的对比。
1.LocalWebServer#
app 启动时,在app 里面开启 WebServer ,相当于 内置服务器。资源与服务都放在app内部。
优点 :后端无须搭建WebServer 供 app 使用,减轻服务端压力。
缺点: 本地服务启动,需要消耗相当大的性能,同时需要处理app 激活问题,实现起来并不容易,开源的 GCDWebServer ,CocoaHTTPServer 已不更新。
2. WKWebView请求拦截#
wkwebView 请求目前有两种 一种是基于系统的NSURLProtocol,一种是iOS 11 引入WKURLSchemeHandler,WKURLSchemeHandler 在隔离性、稳定性、一致性上表现优于NSURLProtocol。
优点: 不修改加载URL,没有跨域问题,且支持网页部分资源离线化,灵活性和兼容性好,腾讯的 开发 VasSonic 开源支持。
缺点: 需要app 端对前端有深入了解,不局限与处理app的代码。
3. 本地路径加载#
app 在请求后,去掉相应的ip ,替换为本地的资源进行加载,类似与打开html 文件。
优点:简单可靠,无需hook和调用私有API,也有相依的公司使用。
缺点:有跨域问题,使用的厂商比较少
总结: WKWebView请求 拦截 基于实现成本低,方案成熟,大厂夹持等特点,可被项目采纳。
技术实现#
离线包基本思路都是通过 webview 统一拦截 url,将资源映射到本地离线包,更新的时候对版本资源检测,下载和维护本地缓存目录中的资源。同时对标签当有标签时,我们使用的图片第三方是Kingfisher,用Kingfisher缓存下来,这样就不需要再次用H5请求图片【改成用本地请求】提升速度。会将图片和视频等非文字内容通过原生组件的方式放在客户端进行渲染,既可以提高渲染效率,也可以减少不必要的流量消耗。

首先实现离线包新版本获取 业务相关的id管理,离线包更新类型管理,包的下载 状态管理,同时离线包具有可选设置项包括频率,缓存策略,调用频率等。
其次是 离线包内的网络请求,以及webView容器创建,清理。
然后是添加离线包相关的log 日志如(离线包更新来源,离线包预加载模式,离线包下载任务状态)。
最后是业务方打包相应的h5 HTML 配置文件,压缩为zip上传到离线包管理平台上。
总体原理图#

app内阶段配置#
首次加载的包 xxx.7zip 复制到项目中如下可看到资源

离线包首次加载配置
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /// 离线包配置(包括激活,日志添加,加载策略等) }
3.离线包内基础内功能如:版本更新管理,下载管理,离线容器管理,离线日志管理,可使用framework 进行封装,可在公司多个app内进行复用。
最终效果#
统计了 APP 在不开离线包方案时,webview 平均加载时长在 1.5-2 秒的范围内(这里是计算的 webview开始加载到导航完成的时间),在上述使用离线包的情况下,打开的时长在 0.25-0.3 秒之间。所以效果还是很显著的,用户的直观感受就是接近于秒开的体验。
参考资料#
[1] [货拉拉H5离线包原理与实践] (https://juejin.cn/post/7103348563479887885#heading-3)
[2] [WKWebView 请求拦截探索与实践] (https://zhuanlan.zhihu.com/p/347592487)
[3] [VasSonic简单介绍] (https://github.com/Tencent/VasSonic)
[4] [WKWebview秒开实践分享及问题解决方案] (https://juejin.cn/post/6887161842406260744#heading-6)