如何打造一个高性能Hybrid App

引言:在多元化的今天,一个热门的移动app,或多或少都会有内在H5在其中。而对于一个有很多运营场景的app来说,这种情况更常见了。试想一下,如果在一个公司,存在很多native和H5同时需要开发的页面,为了节省开发成本,此时如果只开发H5,就需要考虑native的体验了,而这就是本文的目的,如何让native端拥有像加载本地页面一样的速度去加载H5

在app内加载H5速度慢一直是客户端开发的痛点,抛开H5的体验本身与native就有差距不说,如果加载速度还很慢,这将会对用户体验造成巨大影响。那么像做到像native页面一样瞬间加载完H5,思路就会变得比较清晰了--提前在本地存储远程资源包


方案选择

从这个点出发,我们需要考虑,以怎样的形式来提前拿到资源包(css,js,html,通用的图片等),减少这些静态资源的网络请求,增加加载速度。无非就是一下两点:

1.将资源包在app打包阶段直接植入

2.在运行时动态下载资源包

单纯从业务层来说,如果你的业务够简单,其实第一种方式已经完全满足,每次需要新增页面就重新发版嘛,虽然显得有点愚笨,但是还是能满足的。

但是从长远的角度来说,我们要做到尽可能的动态化,动态化是客户端的热点,我们要做到尽量不依赖于版本更新来实现动态化。对于iOS来说,更新机制本身就非常缓慢,要通过app store的审核有时候还需要靠人品,更何况用户也不一定买账,他们不一定会更新我们的app。在这样的情况下,第二种方案就会显得更加友好。


设计加载流程

那么,该怎么设计一套完整的解决方案来满足运行时动态下载资源包呢。

抽出细节,大体上可以归结为下图所示的结构图:

app与服务端交互

我来解释下这个图,我是建立在客户端已经实现socket层协议,所以能与server保持长连接以至于server能主动push数据的情况,实现这种协议蛮复杂的。实际上如果没有这个协议,那就需要client找时机主动去server请求(app启动时请求一次?或者是每隔一段时间请求一次,取决于你),本文以后者为例。

下面我来演示下一个完整的下载新资源包的过程:

1.运营小妹觉得某节日要到了,需要发布一个新的页面,然后在运营后台生成资源包,运营后台会自动更新config,其中包括资源包的version,是否强制关闭加载本地资源包(降级策略,防止这个组件本身有BUG),还有一些hotpatch脚本。并且将资源包根据里面的内容部署到remote database。

2.在合适的时机,client发起http请求向server查询是否有新版本的资源包,并带上本地的config。

3.server根据config里的选项,比对从client拿到的config,发现客户端是旧版本的config,OK,则下发新的config给client,并且发送从database里拿到的资源包(为了加快速度,可以部署到CDN)。

4.client拿到最新的资源包后,在本地进行解密,解压等操作,并映射成对应ULR相对于本地的local file url。比如:http://www.baidu.com这个网址下的静态资源文件在本地的的file://dsalkfjsldfjalsd/目录下。

至此,已经完成资源包的下载。


拦截并加载本地资源包

那么有了资源包后,怎么能让app像native页面的速度去加载H5呢。

其实原理就是对H5请求进行拦截,如果本地已经有对应的静态资源文件,则直接加载,这样就能达到“秒开”webview的效果。

对于iOS而言,这就需要用到NSURLProtocol这个神器了。接下来,分析下它到底是什么东西,我们怎么利用它达到上述效果。

NSURLProtocol能够让你去重新定义苹果的URL加载系统(URL Loading System)的行为,URL Loading System里有许多类用于处理URL请求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSession等。当URL Loading System使用NSURLRequest去获取资源的时候,它会创建一个NSURLProtocol子类的实例,你不应该直接实例化一个NSURLProtocol,NSURLProtocol看起来像是一个协议,但其实这是一个类,而且必须使用该类的子类,并且需要被注册。                                       

--从网上拷贝的

换句话说,NSURLProtocol能拦截所有当前app下的网络请求,并且能自定义地进行处理。

废物不多说,上代码:


NSURLProtocol的子类

这里只介绍与我们需求相关的NSURLProtocol方法。

搞了这么多,其实最核心的就是前四个方法:

+ (BOOL)canInitWithRequest:(NSURLRequest *)request

这个方法的作用是判断当前protocol是否要对这个request进行处理(所有的网络请求都会走到这里,所以我们只需要对我们产生的request进行处理即可)。

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request

这个方法其实很强大,它可以对request进行预处理,比如对header加一些东西什么的,我们这里没什么要改的,所以直接返回request就好了。

- (void)startLoading

重点是这个方法,我们这里需要做一件事,就是自己拼装httpResponse,并且返回给url load system,然后到了webview那一层,会收到response,对于webview而言,加载本地和走网络拿到的response是完全一样的。所以上述代码展示了如何拼装一个httpResponse,当组装完成后,需要调用self.client将数据传出去。

何为self.client,这个东西其实就是protocol与url load system交互的一个对象,系统提供给我们的,这样理解就够了。

需要注意的是,细心的读者会看到else里会有一段代码:

[NSURLProtocol setProperty:@YES forKey:WDHybridResourceProtocolHandledKey inRequest:newRequest];

这个是干什么用的?else的作用是当本地不存在这个文件时,则主动重新发请求,此时又会调用canInitWithRequest,如果不设置flag,则会无限递归了。所以你懂得。

当然,重新发请求自然要实现NSURLConnectionDelegate。


总结

至此,如何快速加载H5已经全部介绍完毕。

附上前后加载速度对比:


加载速度对比



好的,下次再见!

欢迎大家关注微博@kuailejim,我会经常在上面分享一些大家感兴趣的东西。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容