离线存储(Offline Web Applications)浅析


1. 概述

该特性为HTML5的新特性,能够让web程序指定可以缓存在本地的资源,以及缓存策略,使得程序能够在离线时仍然能够运行,也可以使程序在线时也 可以从本地加载资源而不用重新从网络加载。在webkit中,该特性由OFFLINE_WEB_APPLICATIONS宏来控制。

2. 协议内容

在HTML文件中的html标签中添加manifest属性来指定该web application需要用到的manifest文件,而web application作者可以在该文件中指定要缓存的文件列表。




[注:html文件中插入的manifest标签]




implementation 离线_离线存储

[注:manifest文件示例]

manifest 文件是一个缓存清单,把需要缓存在客户端的文件告诉浏览器。manifest是一个mimetype为 text/cache-manifest 的 纯文本文件。

NETWORK, CACHE, FALLBACK 都是可选的。

manifest文件必须以 CACHE MANIFEST 开头

其后需要下载并缓存的文件使用相对或绝对路径皆可,每个资源一行。

NETWORK段表明一些在线资源所在的域,所有这个域下的资源都不会被缓存,即使客户端处于离线状态,也会尝试去请求基于这些域的资源。

CACHE段还没整明白

FALLBACK段下面每行都包含两部分内容,用空格分隔。后半部分是当前半部分路径不能访问时的备选路径




3. webkit中的Offline-Web-Application

webkit中的有关offline-web-application的文件有:

ApplicationCache.[h/cpp]
 ApplicationCacheGroup.[h/cpp]
 ApplicationCacheHost.[h/cpp]
 ApplicationCacheHostInternal.h
 ApplicationCacheResource.[h/cpp]
 ApplicationCacheStorage.[h/cpp]

3.1 几个类的关系如图:




[注: 几个类的关系图]



  • ApplicationCacheHost的职责是面向webkit的接口,负责在webkit加载资源时,从Cache子系统中取得相应资源(如果有的话)。
  • ApplicationCacheGroup与manifest直接相关,一个ApplicationCacheGroup只为一个 manifest服务。每个ApplicationCacheGroup中有一个或多个版本的ApplicationCache,其中有一个 ApplicationCache为“最新的”ApplicationCache。
  • ApplicationCache表征某一个manifest的某一版本的缓存。
  • ApplicationCacheResource表征manifest中的某一项资源。
  • ApplicationCacheStorage可以记录ApplicationCacheGroup、ApplicationCache、 ApplicationCacheResource,每项记录都有唯一ID,在这三个类中,也有相应的表示(storage-id)。

3.2 另一个角度理解几个类之间的关系:

可以通过查看ApplicationCacheGroup、ApplicationCache、ApplicationCacheResource三个类在数据库里的存储方式来理解他们之间的关系。

 




[注:几个类在数据库中的存储形式]



3.3 一个比较简单的manifest处理流程:

 




[注: 离线存储建立的过程]



上图描述了从解析到HTML文件中含有manifest标签,到相关的缓冲处理完毕的一个简化版的过程。 3.4 一个较完整的描述:3.4.1 缓存建立、更新:

  • 开始加载并创建DocumentLoader之时,创建一个ApplicationCacheHost,并与DocumentLoader关联。
  • 在MainResourceLoader调用load的时候,首先通过 ApplicationCacheHost::maybeLoadMainResource调用来检查Offline-Web- Application(以下简称Cache)中是否有主资源文档的缓存,有,则从Cache中加载,否则从网络加载。
  • 加载主资源并解析,当解析到manifest标签,则通过manifest获得与该manifest-url对应的ApplicationCacheGroup对象(如果数据库中有则从数据库中读入,否则新建)。
  • 发起manifest下载流程,如果返回了304(Not  Modified)或者本地保存的manifest文件与下载下来的manifest文件完全一致,则将ApplicationCacheGroup的完 成状态置为NoUpdate,并且退出流程;否则执行以下流程。
  • 下载完毕之后,解析该manifest文件,分析出各个entry(每个entry代表manifest文件中的一个条目)。
  • 发起update流程。调用ApplicationCacheGroup::startLoadingEntry()来下载各个entry,如果 某个entry被返回了404或者410的http错误,则停止update,将ApplicationCacheGroup的状态置为 ‘Failure’,并退出流程。
  • 当所有entry顺利加载完毕,置状态为Complete,并将加载完的ApplicationCache设置为 ApplicationCacheGroup中最新的ApplicationCache,将这个最新的ApplicationCache与当前 ApplicationCacheHost关联。并且通过ApplicationCacheStorage更新数据库。

3.4.2 缓存的使用

当MainResourceLoader或者ResourceLoader在加载资源时,会先检查该资源是否已被缓存,如果已被缓存,并且当前 ApplicationCacheHost关联的ApplicationCache非空而且是Complete状态,则从Cache中取相应资源数据。

4. 与本地存储(Local Storage)的区别

如上所述,离线存储是一个完整的资源缓存体系,包括了javascript,CSS,图片资源,甚至包括了主资源。

而本地存储实际上是只是一个本地的哈希表(key/value对),通常是js用来保存字串的。整个浏览器只有这么一张哈希表。

5. 总结

离线存储为目前的HTML5游戏广泛采用,极大地提高了加载速度。并且考虑到未来的软件web化,离线存储可以有更普遍的应用。