浅淡iOS app加载h5页面

前言

由于目前的工作中,原生app大量嵌入h5页面,很多的功能需要h5来实现,但是由于h5需要从网络加载,在弱网状态或者请求资源大的时候必然出现白屏,再网上搜索后发现并没有一个通用的解决方案,其中VasSonic(手Q的解决方案)侵入性太大,需要整个框架更换成本太大,经过一段时间的实践特总结优化的思路。

总结下主要优化的地方有三块,webview初始化的时间优化静态资源加载的优化, 数据请求前展示的优化

  • webview初始化的时间优化

这个问题在找到webview加载各个app时间时发现的,在webview,loadRequest方法到- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;竟然耗时在1.5s左右,但是再次跳转路由或者加载别的页面时,这个时间基本就没有,猜想可能是第一次loadRequest时同时初始化了webview内部的组件。

加载空白页面的耗时

1-1.png

加载百度的耗时

1-2.png

先加载空白页面,再加载百度的耗时

浅淡iOS app加载h5页面_第1张图片
1-3.png

从上边的测试很明显可以证实我们的猜测

针对上边的问题我们进行了测试,通过先加载h5项目的一个页面再加载真正要展示的页面时间发现第二次加载时并没有load->start的耗时,甚至先加载about:blank也没有这个耗时,所以基本找到了问题。
我们解决做法是做了一个webview的复用池(当然如果项目中同时只有一个webview存在时可以做成单例),在加载闪屏页时进行初始化并加载url(我们项目是vue写的目前是加载一个vue的空白页,其实如果没有做静态资源拦截加载空白页面就好,这个防止网络错误的问题), 在需要展示的地方能过js(location.hash来改变路由或者bridge)来跳转页面。

直接重新loadRequest可能为导航页面重新渲染,能过location.hash或者location.href来改变路由相当于h5内部的跳转,不会重新加载框架

  • 静态资源,能用框架的请求时间

这个是通用的解决方法,因为h5页头有很多静态资源,样式,框架,静态图片,这些都会影响加载速度
针对上边的问题我们解决方案和大部分的一样,将h5的静态资源打包放到本地一份,然后拦截webview请求,静态资源本地读取,ajax请求不拦截

但是由于我们用的webview是wkwebview也就有post请求body丢失的问题目前网上没有可行的解决方案, VasSonic上也是用的uiwebview,项目因为有很多的h5如果换回uiwebveiw会有很多的问题,并且uiwebview性能比较低,占的内存也很大,本身准备放弃,但是在部门老大的提示下,找到了绕过的方案

  1. 前边实现和网上是一样

[NSURLProtocol registerClass:[MyNSURLProtocol class]];

  1. 但是只在打开wkwebview的时候进行拦截

[NSURLProtocol wk_registerScheme:@"http"];
[NSURLProtocol wk_registerScheme:@"https"];

  1. 但是这样会有问题,所以需要h5配合在静态资源文件加载完毕之后通知原生停止拦截

beforeCreate方法里通知原生
[NSURLProtocol wk_unregisterScheme:@"http"];
[NSURLProtocol wk_unregisterScheme:@"https"];

由于静态资源都是get请求,这样就绕过了post丢失body体的问题

第二个问题是因为h5和原生版本不同步的问题,h5更新的速度一般肯定会高于原生的,这样原生里打包的静态文件就会失去作用,并且之前一直不能对h5进行版本控制,比如app强制升级后h5无法兼容低版本

针对这个问题,我们的解决办法是,h5也按版本更新,在app启动的时候与服务器比对是否需要更新静态资源,并且判断当前版本下h5可以访问的最新版本,当更新完成后提示用户然后刷新页面,如果未更新未完成依旧使用旧版本。

  • 数据请求前的展示优化

到了这一步基本js就可以接手控制了,这步我们也还在不断优化中,有以下几个方向

  1. 框架和网络交互分离,因为我们的h5项准备使用自己维护的框架,这个方案在一直慢慢推进,如果分离,就可以像原生一样,就算网络很差也不会出现白屏,会先加载一个框架,等请求回来后再渲染数据

正常使用vue也是可以做到的网上有很多的方案,骨架屏方案等,实在不行可以先加载个loading图片也可以

  1. 请求数据缓存,如果没有请求回来之前可以先使用历史数据展示,对数据请求进行缓存控制,这样即使没有网用户也是可以访问的

由于我们的项目主要是面向b端的,要求数据一致性较高, 主要采用第1种方案进行优化

你可能感兴趣的:(浅淡iOS app加载h5页面)