用HTML5 AppCache运行你的离线web应用
BY SHWETANK DIXIT · 1 JUL, 2010
原文链接 http://dev.opera.com/articles/view/offline-applications-html5-appcache/
介绍
互联网已经成为许多人生活的重要组成,以至于我们无时无刻不在用它们。如果我们即使在断线的时候也能使用他们该有多棒?但直到最近之前(Until recently),都没有什么可行的办法来达成这个目的——然而,在引入W3C HTML5的应用缓存(application cache)特性后,让你的互联网应用在联线和断线状态下都能运行将成为可能。
为什么需要让你的应用离线运行?
每天,互联网应用都在变得越来越复杂,越来越给力。我们可以举出涉及多个领域的可以完成桌面应用功能的互联网应用(比如Google Docs,Picasa等)。但是,他们最大的缺陷在于,他们不能离线状态下工作。
这正是HTML5的新离线存储特性的出发点。它力图寻求一种保存文件于缓存的方法,排除这个缺点,让用户在断线情况下,浏览器仍然可以访问到必须的文件。这些文件可以是HTML,CSS,JAVASCRIPT文件,或者其他网站运行所需的资源。
用应用缓存保存你的文件以供离线时使用
HTML5用于离线互联网应用的特性叫做应用缓存(Appplication Cache),或者简称AppCache。存储在AppCache的文件即使在用户断线的时候也可以被应用访问到。你可以在manifest文件里指明这些你需要保存在AppCache里的文件。
AppCache和一般的浏览器缓存的不同
AppCache与一般的浏览器缓存有诸多不同。首先,两者的目的不同。AppCache的目标是特定的WebApp而浏览器缓存则是针对大部分的网页。一般的缓存会保存几乎所有网页,而AppCache只保存在manifest里面指明的页面。并且,一般的缓存是不稳定的,我们不确定哪些页面(以及其中包括的资源)是可用的。
现在,开发人员可以通过AppCache更加编程式的控制缓存,这意味着在离线状态下,对WebApp我们有更高的确定度和控制度。需要特别一提的是,你可以让多个页面分享同一个AppCache。并且,你可以使用API来决定AppCache的状态,然后,甚至让它自动更新。
Manifest文件
该文件存放在服务器端,指明那些文件需要保存在客户端。让我们好好看看它是怎么工作的。你可以任意命名manifest文件的名字,但最好让它的后缀名是.manifest。每个manifest文件以CACHE MANIFEST开头,后面你可以列出你想保存的文件。注释可以在行首用#标注。一个简单的例子如下:
CACHE MANIFEST #You can also use the CACHE: section header to explicitly declare the following three files. style.css script.js index.htm
Manifest文件必须要有正确的MIME类型:text/cache-manifest。你可以在你服务器上的.htaccess文件上加这么一行来搞定这个问题:
AddType text/cache-manifest .manifest
在HTML里连接manifest文件
现在你已经创建了manifest文件指出需要缓存的文件,下一步就是告诉HTML页面去使用缓存了。为了做到这点,比需要在HTML标签上添加manifest属性,如:
<html manifest=”demo.manifest”>
如果你的WebApp有多个页面,确定他们都连接了manifest文件,否则他们不会成为AppCache的一部分。
使用段首更好的控制AppCache
我们已经看到了一个很简单的关于如何使用manifest文件的例子。通过是使用段首,我们其实可以精确的指明某个文件是否要被缓存。
明确定义需要被缓存的文件
你可以使用cache:段首来明确声明那些文件需要被缓存。例如,前面那个manifest文件可以写成这样,功能不变:
CACHE MANIFEST CACHE: style.css script.js index.htm
唯一的差别是在这个例子里我们明确的声明全部这些文件都会成为AppCache的一部分,这里有个很简单的实例。
需要重点说明的是,里面提到文件的路径是相对于manifest文件的路径的。在这个例子里,我们假设这些文件都是和manifest文件在同一个文件夹里的。并且,你可以使用相对路径也可以使用绝对路径。
当文件明确声明在CACHE:中,即便你在线,只要manifest文件没有变动,那它们都将从AppCache(而非服务器)中读取,然而,如果浏览器发现一个更新了的manifest文件,新的缓存会再次根据新manifest文件的指示下载相应的文件。所以AppCache可能不适合内容变动很快的网站,比如新闻博客等。但对于专注于某个应用,需要离线工作的WebApp却十分有用(如日历,todo list等)。
如果我要文件绕过缓存直接从服务器下载怎么办?
如果一个页面与一个manifest文件关联,那么只有那些被提到的文件会被尝试读取,无论用户是否在线。然后,也许会存在一些情况你需要一些文件在用户在线的时候绕过缓存,然后从服务器下载最新的文件取代缓存中的文件(比如,一个CGI脚本的动态内容)。
基本上,如果一个页面和manifest文件关联,那所有关于它的文件的网络流量都会被阻隔,于是这些文件要么从AppCache里读取,要么读取失败。而段首NETWORK:给出了这条规则的例外。你可以用段首NETWORK:来声明那些文件不该被缓存,于是它们就会从服务器直接下载,永远不会成为AppCache的一部分。NETWORK:和浏览器的一般缓存头(normal cache header)是分开的,所以如果一个文件应该会被浏览器的一般缓存保存,那即便它被指定在NETWORK:之下,它还是会被那样被保存(跟其他在AppCache中没有指定的文件一样)。
CACHE MANIFEST CACHE: style.css script.js index.htm NETWORK: style2.css
在上面的例子中,style2.css将总是从服务器下载而不会成为AppCache的一部分。值得注意的是,如果你有太多文件要列在NETWORK:下,你可以用通配符*,这样所有的url都被准许在用户在线的时候从服务器下载文件(译者按:这个通配符的作用应该不只于此吧)。
看一下这个例子。你会注意到当你离线并重新加载页面,页面重新加载了,但背景样式也消失了。这是因为背景样式是写在NETWORK:下的style2.css里面的,于是它不会被保存,只有当你在线并刷新的时候才会加载。
提供后备(fallback)内容
(无良的译者按:鉴于callback叫做回调,我觉得fallback是不是可以叫衰调)
段首FALLBACK:是用来定义后备内容,取代无法读取或者读取不完全的文件:
CACHE MANIFEST CACHE: style.css script.js index.htm NETWORK: style2.css FALLBACK: main_image.jpg backup_image.jpg
后备内容是会被缓存的,并且只在主要内容无法读取的时候才被使用。上例中,backup_image.jpg缓存在AppCache里面,所以,如果main_image.jpg无法读取,backup_image.jpg就会替代它的位置。看下这个manifest文件——如果你访问这个页面,断线,刷新,浏览器会试图加载图片,但因为你不在线(图片也没有被缓存),它不会被读取到,于是备用内容就会取代它的位置(浏览器会首先花点时间读取主要内容,然后才使用备用内容,请耐心等待——译者按:好像没用多少时间)
一个提供备用内容给多个图片的例子看这里。
待续