货拉拉H5离线包原理与实践

14,249 阅读9分钟

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改成了三层结构:

image.png

增强WebVC和基础WebVC 功能独立,已分成独立的仓库,由不同的开发维护,维护性大大提高。货拉拉基础WebVC容器代码暂未开源,开源代码中改成简化版实现,可自行定制和修改。

4.3 性能优化

1)查询并行化

目前已有多个H5页面采用离线包,为了提高查询效率,多个业务离线包检查的请求采取并行请求的方式。由于HTTP2支持多路复用,所以查询时共用一个NSURLSession对象,多次查询操作自动复用一个TCP连接,减少建立连接次数。考虑到后端改造成本问题,目前不支持聚合查询,计划在后续版本中完善。

image.png

2)下载任务去重

下载过程也是并行进行,可同时下载多个离线包。由于查询操作有多个触发时机,存在重复下载的情况。为了节省流量,采用下载URL作为key,不重复下载正在下载或已下载的文件。

3)启动预下载

大部分离线包查询和下载的时机为打开H5页面时,由于离线包查询、下载、解压总体耗时超过1秒,导致首次打开无法命中离线包。所以货拉拉离线包支持配置部分离线包在启动时检查和下载离线包,提升首次打开H5页面离线包命中率。配置json格式为:

{

   "predownloadlist": //选填。需要启动就下载的离线包列表清单
    ["test-offline"]
}

4)断点续传

移动端网络稳定性不如固定网络,会出现因为无网络而导致下载中断的情况。货拉拉离线包接入了自研的下载SDK,支持断点续传功能,节省了用户下载流量和时长。由于下载SDK代码暂时未开源,离线包对外开源代码中采用简化版本代替,没有实现断点续传功能。

5)解压异步化和串行化

解压过程是CPU和IO密集型操作,放在子线程中处理,有多个文件需要解压时,采用串行队列的方式,一次只解压一个文件,避免同时解压多个文件影响客户端性能。

4.4 可靠性设计

1)解压操作可靠性设计

文件解压耗时较长(大约30ms),如果程序异常退出可能会出现解压操作完成一半的情况,影响后续离线包功能。所以文件解压操作采取先解压,然后重命名,保证最后得到的文件完整性。同时当离线包正在使用时,一般情况下采取先解压,下次生效的策略,极端情况下立刻生效,但会导致页面强刷,影响用户体验,使用较少。离线包存放时使用tmp、new、cur三个文件夹,不采用版本号命名,简化离线包缓存管理逻辑。解压细节如下:

image.png

2)三重降级策略

客户端自动降级。本地没有离线包时,客户端会自动将启用离线包的H5页面降级为线上H5页面。

远程配置降级。可以设置局部降级,即临时将某个使用离线包的H5页面降级为线上,也可设置全局降级,关闭所有页面的离线包功能。配置json为:

{
    "switch": 1, //总开关,1开启,0关闭
    "disablelist": //选填,配置禁用某个离线包
     ["act-test"],
}

服务端接口降级。 服务端提供的离线包查询接口可设置将某个页面降级为线上H5,亦可配置客户端更新离线包后强制刷新。

降级策略流程图如下:

image.png

3)性能监控

货拉拉对webview的加载成功率,错误码、耗时进行了统计上报,通过监控面板查看。

此外离线包SDK还有离线包下载,请求,解压的耗时、结果数据上报。监控和上报采取的接口扩展方式,接入方根据业务特点选用具体的数据上报SDK。

4.5 效能优化

1)开发者工具

为了方便调试和查看,离线包中包含了开发者工具,仅在Debug模式下才能使用,可查看离线包版本和清除离线包缓存。

2)离线包和URL映射配置化

客户端webview通过URL是否有offweb参数判断该页面走线上请求还是加载本地离线包。URL来源广泛,有客户端硬编码、运营系统下发、JS action调用多种来源,手动修改URL效率太低,因此通过远程配置,自动给指定URL添加离线包参数并命中对应的H5离线包。

image.png

配置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

github.com/yangfangkuo…

WKWebView完美网络请求拦截 www.jianshu.com/p/7b28cbd8f…

腾讯vassonic blog.csdn.net/oqzuser1587…