前文讲到 仅有一种阻拦 WKWebView 资源恳求的方法,本文将会把整套预加载和缓存计划整理下,供咱们借鉴参阅。

背景

计划方针

  1. 在 App 中,让Web 在线页面到达Web 离线包加载功率。
  2. 无需改动当时前端开发的流程以及基建。

在线计划与离线计划

简略讲一下在线计划到达离线计划的区分。

在线计划

Web 容器直接加载远程 URL,本质上与在浏览器上加载 URL 没什么不同,在完成上供给一套 JSSDK,供给一些局限的才能,比方获取 Token、获取当时信息等。

要害长处:前端 / 终端容器基本上是解耦的,只需适配竖屏 UI 的 Web 页面都能够在在线计划中加载。对前端开发体会来说也是很舒畅的一种计划,只需关怀前端自身即可。

要害缺点:

  1. 用户体会上差强人意,再怎样优化,用户也能感知出这个是浏览器加载的方法。
  2. JSSDK 只能供给局限的才能,因为有跨域问题,这里的跨域不是域名间跨域,而是 App 容器和 HTTP 间的跨域问题,比方 Web 页面拜访 App 本地资源。
  3. 这一点是对第二点局限才能的补充,JSSDK 还需求各种加密安全确保(比方授权 Token 与 URL 绑定的方法),但其实也没什么卵用,这也是微信公众号多年不更新 JSSDK 才能的原因,因为无法确保才能安全。

这更适合资讯类、营销类、广告类等非中心事务完成。这其实也符合 iOS 对 Web 开发的界说,非中心事务,理论上 Web 页面不能超过整个 App 的 35%,否则有拒审的危险。

离线计划

Web 容器加载的是 App 本地的资源,这也是小程序能成的最重要的基础(原生混合烘托那些只是体会优化,所以这里不单指微信小程序,比方冷门点的云闪付小程序,其实便是把在线 URL 打包成压缩包上传)。

要害优缺点便是在线计划反过来,用户体会更好,能用各种 App 上的底层才能,但开发体会更差,没办法直接融入前端体系。

开发体会差的首要问题在于:

  1. (要点)调试难,微信/支付宝都有自己的 IDE 开发调试东西,“基本” 能够确保在 IDE 的效果与在 App 上是一致的(坑也是多的很,特别是支付宝小程序)。
  2. 无法直接复用前端架构/生态/基建,比方 BFF 层就用不了,导致相同功用需求开发离线版、在线版,重复劳动。

在线页面离线化

列举了以上的优缺点,那能够只需两个长处都要吗?

答案肯定是能够,否则笔者在这说什么废话 ~

在降本增效的大前提下,前端开发一套 Web 页面,能够在各个容器中正常运用,且到达与离线包相同的体会,便是咱们的作业方针了。

思考

如何离线化在线页面,其实能选择的方法也不多,许多大厂也会选择运用一个极小化的 WebView 内核来提早加载资源,这样的好处也很明显,App 容器上无需更多的关怀缓存的完成方法。

但带来的问题便是依托 WebView 进行资源缓存,那在预加载上就必须启动一个 WebView 容器,这一点其实有性能损耗的,假如有多个页面需求预缓存,那就必须开多个容器或许供给一个预加载行列,控制起来也是尤为费事,特别在预加载完之前用户就进入页面的情景下,缓存意外也是有或许的。

那对咱们来说,在抛弃了运用极小化的 WebView 内核进行资源缓存的计划后,能选择的便是提早把页面上的资源下载到 App 本地,然后通过恳求阻拦的方法进行本地资源加载。

计划

在之前的计划上,是通过直接下载 HTML,然后通过正则的方法解析其间的 CSS、JS 文件,进行提早预加载。

但这会有一个问题,那便是不能去缓存 HTML 文件,否则会导致更多的问题:

问题1: 缓存更新不及时。

尽管每次启动后都会预加载最新的页面,但假如预加载未完成且前端有更新,用户还是会返回到旧的 HTML。

这一点能够运用严厉形式,在预加载之前,先整理掉缓存,拜访的时候假如没有缓存,页面会按原始状况加载,不再运用缓存加速。

那关于用户来说每次重启 App 后都会拉取最新的。

问题2: 服务器颤动等状况下,下载到不正确的页面。

这一点是完全有或许的,究竟咱们是把页面当作资源下载下来,并没有通过 WebView 解析,所以咱们要检测下载的内容是否正确。


而假如没有对 HTML 进行缓存,相当于离线化计划少了一条腿,并不能完全的到达咱们想要的加载秒开率。

那在优化后的计划是这样:

「最佳实践」WebView 预加载与资源缓存

预加载

从上图中能够看到,咱们在 Web 中增加了一个 manifest 的清单文件,它是一个 JSON 格式文件,里边描绘了:

  • indexMD5 HTML 内容校验标识
  • indexURL HTML 拜访地址
  • assets 资源列表

那在 App 上,预加载要做的事就变成:

  1. 通过 get 恳求,拿到 mainfast.json
  2. 依据indexURL下载 HTML 内容
  3. 依据indexMD5校验下载内容是否正确
  4. 依据assets下载资源列表

责任更明晰了,且稳定性变的更高。

而预加载的时机上:

  • 在主页加载后3秒执行,尽量不影响主页加载功率。
  • 在用户从后台返回到前台时执行。

缓存

整体缓存分为几个部分:

  1. 清单和路由的联系缓存,这个选用 key-value 的方法耐久化存储,key是清单地址,value是对应的路由列表。
  2. 清单对应的 HTML,也是选用 key-value 的方法耐久化存储,key是清单地址,value是 HTML 内容。
  3. 清单对应的资源文件,选用本地文件映射的方法,把资源文件一一映射成本地路径,所以能够直接判断文件是否存在,不存在再下载,提高缓存性能。

「最佳实践」WebView 预加载与资源缓存

而这还要留意处理的是缓存冗余,关于前2种 KV 缓存来说,缓存并不会产生冗余。但关于资源来说,会跟着前端发包而变得越来越多,这时候就需求整理掉这部分过期资源。

整理手段也很简略,分为2步:

  1. 获取最新的 manifest,对assets进行差集对比,标记出已过期的资源。
  2. App 重新启动后,整理过期资源。

这样确保在确保预下载过程中,用户翻开网页不会产生资源丢掉等反常状况。

「最佳实践」WebView 预加载与资源缓存

稳定性

安全第一一套新计划落地前,需求有齐备的监控手段以及可快速降级手段,来防止上线危险。

而对缓存及预加载的要求,便是一旦产生反常状况,及时扔掉缓存,直接加载页面。这在有了清单文件后,变得非常可行:

  1. mainfast 是 JSON 数据,当返回反常场景下,读取 JSON 失败,则抛弃本次缓存。
  2. 下载的 HTML 校验 md5 失败,则抛弃本次缓存。
  3. 增加白屏监测,呈现白屏现象则及时抛弃缓存并改写页面。
  4. 灰度呈现问题反应,及时封闭功用开关,降级为之前的完成方法。

总之便是一有反常就丢弃缓存,一有反应及时中止试验。

资源拜访

通过恳求阻拦的方法,具体见:仅有一种阻拦 WKWebView 资源恳求的方法

后续

这只是整套 Web 容器计划的一小部分,但笔者觉得也是值得拿出来共享一下,新 Web 容器会在近期灰度上线测试,到时候还有什么坑笔者也会继续共享 ~


感谢阅读,假如对你有用请点个赞 ❤️

「最佳实践」WebView 预加载与资源缓存

本文正在参加「金石计划」