youngwind / blog

梁少峰的个人博客
4.66k stars 385 forks source link

Hybrid App中web资源的离线存储与更新机制研究 #79

Open youngwind opened 7 years ago

youngwind commented 7 years ago

问题

在Hybrid App中,需要频繁访问H5页面。要是每一次的页面请求都通过网络从远端拿的话,不但会消耗很多的用户流量,而且在网络不好(2G、3G)的时候会有巨大的延迟。 如何解决? --> 把H5页面直接放到app包里面,随版本发布,每次请求页面都从本地拿。 是的,早就有人这么做了。天猫、淘宝APP越来越大的安装包体积,原因之一就是放入了越来越多的H5资源。不过这个方法有局限性:第一,安装包体积不能无限增大;第二,APP发版之后web资源需要更新怎么办?所以这个方法只适用于存储一些基本不怎么变的web资源。

分析

假设我有这样的一个APP。从每一个入口点击进去都是一系列不同的H5页面,你可以简单理解成四个不同的主要功能。我们称它们为“组件包”,所以这里就有四个组件包,对应到开发的时候就相当于有四个前端项目。

5554_nexus_5x_api_23

我们的目标是:当FE对任意一个项目作出修改之后,APP都能够动态更新对应组件包。 下图是对应的实现方案。 web

实现

方案实现的demo分别是下面三个仓库:

  1. 安卓客户端
  2. 组件平台前端
  3. 组件平台后端

    遗留问题

    所谓HTTP长连接

目前实现的方案有一个问题:只有当用户启动APP的时候,才会去检查组件包是否更新,这样会导致更新的不及时。当然,我可以通过增多检测的时间点来缩短这个延时。但是,如果想要实时更新组件包,其实这本质上是“客户端与服务器之间的实时通信”问题。经典的解决方案有比如:短轮训、长轮训、websocket。我一开始在查阅很多这个更新机制相关的资料的时候,频繁出现”HTTP长连接“这个字眼,但是又都语焉不详,没有好好解释。我误以为HTTP协议本身可以实现实时的服务器推送,折腾了数天都没法实现。后来才发现”其实所谓HTTP长连接本质上只是TCP的长连接,通过HTTP header中设置connection:keep-alive来启动,能做到的不过是保持TCP通道,让之后的HTTP请求复用这一个通道,好处是省略了TCP的三次握手而已,是没有办法做到服务器推送的。要想实现服务器推送,还是需要用原始socket或者websocket来做。“实现这个难度比较大,这次就先不做,留待之后再优化。而且不仅组件包的实时更新需要用到socket,安卓APP的消息提醒机制也需要用到socket,所以之后还是得好好研究这个。

虚拟路由问题

做到最后才发现漏了一个功能。。。那就是”组件包解压到本地之后,如果引用的问题。“比如说APP的webview想加载的是:”http://www.example.com/package/index.html“ 如何映射到APP内的对应目录呢?如果APP内没有离线资源,还要让webview加载远端的线上资源等等。

参考资料

  1. Hybrid APP架构设计思路
  2. 极致的 Hybrid 混合式开发(去啊App Hybrid 实战)
  3. 极致的 Hybrid:航旅离线包再加速!
  4. APP的推送是咋回事
  5. Android 长链接的尝试
  6. Comet技术详解:基于HTTP长连接的Web端实时通信技术
  7. 用node.js实现HTML5原生的comet(长连接)
  8. 互联网推送服务原理:长连接+心跳机制
  9. HTTP长连接和短连接
  10. Android zip文件压缩与解压库:zip4jzip4j使用示例
  11. Android SQLite详解
  12. Android使用ion库下载文件
cxz1305644 commented 6 years ago

http2 是可以实现服务器推送的