1 把Html5页面嵌入到Zip包中
App中会使用很多HTML5页面。我们一般使用内置的WebView来打开一个外部的URL地址,这样一来,速度就肯定不如App原生的页面快了。
我们可以打开几个App的Html5页面来进行比较,差距立刻就能看出来。当年我就是被老板追着问为什么竞争对手的App打开Html5也就1-2秒,而我们的App加载Html5页面就跟牛车一样慢。
我看过很多App的内部结构,发现无论是ipa还是apk包中都会有一个Zip压缩包,里面存放着要加载的Html5页面、图片、CSS和JS文件。App每次启动的时候,会启动一个线程,异步把Zip包解压到本地的某个目录下,然后每次从本地读取Html5页面,这样就不用每次从服务器加载Html5页面了。
也许有人会问,如果这个Zip包里的内容有变化怎么办?比如说新增了图片或是修改了Html5页面的内容。我们需要有个版本控制机制。每次加载Html5页面之前,先问一下服务器,当前Html5页面的版本是什么,如果与本地保存的版本号相同,就直接加载本地的Html5;否则,就从服务器重新下载一个新的Zip包,仍然解压到本地相同的目录下。
如果客户端自带Zip包版本比较旧,那么每个新下载的用户打开App都要下载服务器最新版本的Zip包。这样不好,会导致Zip包很大,要下载很久,所以每次发版前,都要把服务器上最新的Zip压缩包放到App安装包中。
2 Zip包的增量更新机制
即使如此,每次有新版本的Html5,都要下载一个最新的Zip包,还是很慢。为此我们要减小Zip的体积。我们知道,Zip包中包括Html5页面、图片、CSS和JS文件,但并不是每次升级每个文件都要更新,我们要把那些不随版本升级而变化的文件挑出来,压缩成common.zip,放到App包中,仍然是第一次启动App后解压缩到本地。这样每次Html5页面的版本要升级,只要确保要下载的Zip包中只包括新增的和修改的文件就可以了,从而确保了Zip包的体积最小,可以快速下载到App,仍然解压到相同的目录下,如果有相同的文件则将其覆盖。我们称这种机制为“增量更新”。
我说的这种增量包,只包括新增的和修改的文件,对于删除的文件,我们不用去管它,就把它扔在手机的本地目录下好了。
也许有人会问,当App正在访问本地一个html页面的时候,恰好本地解压Zip包时要覆盖这个文件,那么会不会像PC机那样弹出个窗口提示“该文件正在使用中,复制工作不能进行”?经过测试,在手机上不存在这个问题。
就算是增量更新,也要控制增量包的大小在100KB以内。
3 制作Zip增量包
那么问题来了,如何制作增量包?比如说,Html5内置在App中的版本号是1.0,两天后线上Html5版本更新为1.1,于是我们需要提供一个增量压缩包供用户下载,这是1.1和1.0之间的增量。又过了两天,线上Html5版本又更新到1.2了,因为我们不确保所有的用户的Html5本地版本都从1.0升级到1.1了,所以这时我们就要提供两个增量压缩包,一个是1.2和1.1之间的增量包,另一个则是1.2和1.0之间的增量包。随着Html5版本的不断升级,每次要生成的增量压缩包会越来越多。
我们不能每次手动打增量包,这是要累死人的。我们需要记录每个Html5版本对应的目录和文件,放到Git服务器上是个不错的选择。GIT提供这样的命令行工具,比较两次提交之间的区别。此外,需要做一个小工具,它具有一个“发布”按钮,点击这个按钮后将会从GIT服务器中逐个比较当前版本1.2和历史版本1.0、1.1之间的区别,分别打包成Zip,然后发布到服务器上提供下载。
这是件很繁琐的事情。但是你会发现,虽然后台生成增量压缩包的逻辑超级复杂,但是App的业务逻辑却非常简单了,App只要知道增量压缩包的下载地址就够了。
即使如此,如果增量包中的图片过多,那么这个增量包还是会很大。这时我们就要控制增量包中图片的数量,只要保证App首屏显示的图片在增量压缩包中即可,至于屏幕外的图片,还是使用http://www.aaa.com/aa.jpg这样的URL,同时要在App的WebView控件上建立图片缓存,以确保再次访问这个URL时不会重新加载图片浪费用户的时间和流量。
对于后台运营人员,她们要经常上一些新活动,以至于每时每刻都有可能更新Html5的内容并希望用户能立刻看到这些变化。这时候手动点击Publish按钮就会跟不上节奏了。一种好的解决方案是,在服务器创建一个Task,每10分钟执行一次,把这10分钟内有改动的内容重新打增量压缩包。服务器端业务逻辑仍然会很复杂,但是极大的提高了客户端的信息更新频率。
有的Html5页面会在html页面中使用ajax调用网络接口获取数据,当我们将其打包成Zip解压到手机本地再去加载的时候,ajax因为存在跨域的问题而不能访问到网络接口数据,这时我们就要同时从App的代码和Html的代码进行配置,才能解决这个问题。
4 使用WebView预先加载Html5并缓存到本地
前面的设计太复杂了。
为了快速加载Html5,我们可以不择手段。比如说,利用WebView控件的缓存技术。如果在App的某个页面设置了WebView的缓存,那么再次打开相同的URL时,如果没有过期,就会使用本地的缓存数据。但即使如此,也不能解决第一次加载Html5时很慢的问题,但是我们可以在上一个页面创建一个WebView,让它预先加载这个URL,这样就能提前把Html5页面缓存到本地,一定要记住,要把这个WebView设置为不可见,否则就露馅了。
这样做虽然大幅提升了Html5加载的速度,但是却非常耗流量,采用这个策略的时候要谨慎。
包建强的无线技术空间 code小生