1.前言
货拉拉自研H5离线包SDK,能显著提升H5打开速度,已在多个业务中落地。车型介绍页使用离线包前后打开效果如下:
图1 使用离线包前 | 图2 使用离线包后 |
---|---|
货拉拉自研离线包具有如下特点:
安全可靠:无hook,无私有API,三重降级策略。
容易维护:三层架构模式和模块化设计。
功能完备:功能可配置,数据埋点,开发者工具等功能一应俱全。
开源代码地址:github.com/HuolalaTech…
团队介绍:货拉拉移动技术团队juejin.cn/user/176848…
2.背景
Web 技术相信大家非常熟悉,它具有快速迭代发布的天然优势,在货拉拉App中广泛使用,比如金秋拉货节、余额、车型介绍页等,但也存在加载速度慢,体验差等问题。目前优化Web页面体验方案比较多,有Flutter、React Native、小程序、离线包,其中离线包技术对现有H5页面改造成本小,技术最为成熟和稳定。
3.行业方案
腾讯开源了离线包方案VasSonic(github.com/Tencent/Vas…
方案名 | 优点 | 缺点 | 备注 |
---|---|---|---|
加载本地路径 | 简单可靠,无需hook和调用私有API | 有跨域问题,影响cookie和localstorage,H5需做少量改动 | 货拉拉方案 |
请求拦截 | 不修改加载URL,没有跨域问题,且支持网页部分资源离线化,灵活性和兼容性好 | iOS端目前提供的NSURLProtocal和WKSURLSchemehandler拦截方案有缺陷,前期实现成本高 | www.jianshu.com/p/8f5e1082f… 网易云音乐方案zhuanlan.zhihu.com/p/347592487 |
本地Web Server | 兼容性好 | 对客户端耗电和CPU性能有影响 | 暂未发现有公司采用,juejin.cn/entry/68449… |
Service Worker | 前端兼容性好 | iOS端WKWebView不提供官方支持,实现技术难度大 | 爱奇艺方案zhuanlan.zhihu.com/p/148931732 |
上述几种方案,本地搭建Web Server方式对客户端性能影响大,先排除,Service Worker方案由于iOS端不支持,不考虑。资源拦截方案兼容性好,但需要解决WKWebview拦截网络请求难度大的问题,开发和测试工作量大,暂不用。结合实现成本和技术可靠性最后采取加载本地路径的方案。
4. 技术实现
H5离线包的基本原理是将html、js、css、图片等静态资源打包成压缩包,然后下载到客户端并解压,H5加载时直接从本地读取静态资源文件,减少网络请求,提高速度。加载本地文件路径存在的问题和解决方法:
存在问题 | 解决方法 |
---|---|
cgi请求跨域问题 | 在网关或者后端服务的跨域请求头增加null域支持 |
cookie跨域问题 | 目前静态js中无cookie操作,没有cookie跨域问题 |
localstorage跨域问题 | 暂时不涉及域名隔离问题,如果有需要,采取调用原生的方式解决 |
绝对路径问题离线模式不支持问题 | 改成相对路径 |
4.1 总体流程
如下图所示:
客户端启动后,先去远程配置服务器拉取离线包相关的功能配置,然后检查更新,如果有更新则下载离线包。webview加载时,如果本地缓存命中,则从本地磁盘加载html、js、css、图片等静态资源。
H5离线包和线上H5类似也能进行更新和升级,有三个更新时机:
1)webview容器打开时更新。开启离线包功能的H5页面每次打开时,会去检查对应的离线包是否有更新。如果有更新,则下载离线包到本地,绝大部分场景是下次打开时生效。
2)启动查询离线包更新。对于实时性要求比较高的页面,可配置在启动时更新离线包。
3)长连接推送实时更新。更新实时性要求极高的场景使用。
4.2 架构改进
之前货拉拉webview容器(后续简称WebVC)采用的是两层结构,每个业务方从基础WebVC派生出自己的业务WebVC容器。两层结构在接入离线包时遇到如下问题:
离线包接入方案 | 优点 | 缺点 |
---|---|---|
集成到业务WebVC容器 | 不影响基础WebVC功能,影响范围小 | 通用性差,每个业务WebVC都需要修改,接入成本高。 |
集成到基础WebVC容器 | 业务方接入简单,升级基础WebVC即可 | 基础WebVC会变得臃肿,增加了离线包,调试工具,埋点功能,后续维护成本高。 |
为了既不造成基础容器臃肿,维护成本高,也要方便业务方快速接入,将webview改成了三层结构:
增强WebVC和基础WebVC 功能独立,已分成独立的仓库,由不同的开发维护,维护性大大提高。货拉拉基础WebVC容器代码暂未开源,开源代码中改成简化版实现,可自行定制和修改。
4.3 性能优化
1)查询并行化
目前已有多个H5页面采用离线包,为了提高查询效率,多个业务离线包检查的请求采取并行请求的方式。由于HTTP2支持多路复用,所以查询时共用一个NSURLSession对象,多次查询操作自动复用一个TCP连接,减少建立连接次数。考虑到后端改造成本问题,目前不支持聚合查询,计划在后续版本中完善。
2)下载任务去重
下载过程也是并行进行,可同时下载多个离线包。由于查询操作有多个触发时机,存在重复下载的情况。为了节省流量,采用下载URL作为key,不重复下载正在下载或已下载的文件。
3)启动预下载
大部分离线包查询和下载的时机为打开H5页面时,由于离线包查询、下载、解压总体耗时超过1秒,导致首次打开无法命中离线包。所以货拉拉离线包支持配置部分离线包在启动时检查和下载离线包,提升首次打开H5页面离线包命中率。配置json格式为:
{
"predownloadlist": //选填。需要启动就下载的离线包列表清单
["test-offline"]
}
4)断点续传
移动端网络稳定性不如固定网络,会出现因为无网络而导致下载中断的情况。货拉拉离线包接入了自研的下载SDK,支持断点续传功能,节省了用户下载流量和时长。由于下载SDK代码暂时未开源,离线包对外开源代码中采用简化版本代替,没有实现断点续传功能。
5)解压异步化和串行化
解压过程是CPU和IO密集型操作,放在子线程中处理,有多个文件需要解压时,采用串行队列的方式,一次只解压一个文件,避免同时解压多个文件影响客户端性能。
4.4 可靠性设计
1)解压操作可靠性设计
文件解压耗时较长(大约30ms),如果程序异常退出可能会出现解压操作完成一半的情况,影响后续离线包功能。所以文件解压操作采取先解压,然后重命名,保证最后得到的文件完整性。同时当离线包正在使用时,一般情况下采取先解压,下次生效的策略,极端情况下立刻生效,但会导致页面强刷,影响用户体验,使用较少。离线包存放时使用tmp、new、cur三个文件夹,不采用版本号命名,简化离线包缓存管理逻辑。解压细节如下:
2)三重降级策略
客户端自动降级。本地没有离线包时,客户端会自动将启用离线包的H5页面降级为线上H5页面。
远程配置降级。可以设置局部降级,即临时将某个使用离线包的H5页面降级为线上,也可设置全局降级,关闭所有页面的离线包功能。配置json为:
{
"switch": 1, //总开关,1开启,0关闭
"disablelist": //选填,配置禁用某个离线包
["act-test"],
}
服务端接口降级。 服务端提供的离线包查询接口可设置将某个页面降级为线上H5,亦可配置客户端更新离线包后强制刷新。
降级策略流程图如下:
3)性能监控
货拉拉对webview的加载成功率,错误码、耗时进行了统计上报,通过监控面板查看。
此外离线包SDK还有离线包下载,请求,解压的耗时、结果数据上报。监控和上报采取的接口扩展方式,接入方根据业务特点选用具体的数据上报SDK。
4.5 效能优化
1)开发者工具
为了方便调试和查看,离线包中包含了开发者工具,仅在Debug模式下才能使用,可查看离线包版本和清除离线包缓存。
2)离线包和URL映射配置化
客户端webview通过URL是否有offweb参数判断该页面走线上请求还是加载本地离线包。URL来源广泛,有客户端硬编码、运营系统下发、JS action调用多种来源,手动修改URL效率太低,因此通过远程配置,自动给指定URL添加离线包参数并命中对应的H5离线包。
配置json格式如下:主要通过host,path配置匹配规则。
{
"rules" :[
{
"host" :[
"test1.zzz.cn" ,
"test2.zzz.cn"
],
"path" :[
"/testapp"
],
"offweb" : "test-offline1"
},
{
"host" :[
"test3.xxx.cn" ,
"test4.xxx.cn"
],
"path" :[
"test/offweb" ,
"test/abc"
],
"offweb" : "test-offline2"
}
]
}
5. 收益分析
H5离线包经过多个业务上线验证,性能稳定,收益明显。
5.1 加载速度提升
改造完成的H5页面,平均加载速度从2s提升至1s。部分页面详细数据如下:
5.2 加载成功率提升
页面主框架(不考虑动态数据)加载成功率从96%提升到100%。
6.后期工作与展望
1)扩大开源范围。断点续传下载SDK,日志SDK后续会考虑开源。
2)单元测试用例完善。增加更多单元测试,保证稳定性。
7.参考资料
货拉拉离线包开源地址github.com/HuolalaTech…
携程增量更新zhuanlan.zhihu.com/p/34125968
Service worker zhuanlan.zhihu.com/p/148931732
WKWebView完美网络请求拦截 www.jianshu.com/p/7b28cbd8f…
腾讯vassonic blog.csdn.net/oqzuser1587…