背景
为了快递迭代、更新,公司app有一大模块功能使用H5实现,但是体验比原生差,这就衍生了如何提高H5加载速度,优化体验的问题。此文,记录一下自己的心路历程。
腾讯bugly发表的一篇文章《移动端本地 H5 秒开方案探索与实现》
[1]中分析,H5体验糟糕,是因为它做了很多事:
初始化 webview -> 请求页面 -> 下载数据 -> 解析HTML -> 请求 js/css 资源 -> dom 渲染 -> 解析 JS 执行 -> JS 请求数据 -> 解析渲染 -> 下载渲染图片
一般页面在 dom 渲染后才能展示,可以发现,H5 首屏渲染白屏问题的原因关键在于,如何优化减少从请求下载页面到渲染之间这段时间的耗时。所以,减少网络请求,采用加载离线资源加载方案来做优化。
离线包
离线包的分发
使用公司的CDN实现离线包的分发,在对象存储中放置离线包文件和一个额外的 info.json 文件(例如:https://xxx/statics/info.json):
{
"version":"4320573858a8fa3567a1", "files": [ "https://xxx/index.html", "https://xxx/logo.add928b525.png", "https://xxx/main.c609e010f4.js", "https://xxx/vender.821f3aa0d2e606967ad3.css", "https://xxx/manifest.json" ]}
其中,app存储当次的version,当下次请求时version变化,就说明资源有更新,需更新下载。
离线包的下载
离线包内容:css,js,html,通用的图片等
下载时机:在app启动的时候,开启线程下载资源,注意不要影响app的启动。
存放位置:选用沙盒中的/Library/Caches。
因为资源会不定时更新,而/Library/Documents更适合存放一些重要的且不经常更新的数据。
更新逻辑:请求CDN上的info.json资源,返回的version与本地保存的不同,则资源变化需更新下载。注:第一次运行时,需要在/Library/Caches中创建自定义文件夹,并全量下载资源。
1、获取CDN和沙盒中资源:
NSMutableArray *cdnFileNameArray = [NSMutableArray array];//todo 获取CDN资源NSArray *localExistAarry = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:nil];
2、本地沙盒有但cdn上没有的资源文件,需要删除,以防文件越积越多:
//过滤删除操作NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", cdnFileNameArray];NSArray *filter = [localExistAarry filteredArrayUsingPredicate:predicate];if (filter.count > 0) {
[filter enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {