离线Web应用-HTML5 Cache Manifest试验

原文地址 http://www.bennadel.com/blog/1944-Experimenting-With-HTML5-s-Cache-Manifest-For-Offline-Web-Applications.htm
译者 Vilic Vane (www.vilic.info)

(译者注:第一次翻译东西,限于英文水平,不足之处请见谅.另外,原文作者使用的是ColdFusion,代码中有些内容并非浏览器最终获得的内容,请注意区别.然后空了会争取翻一下文件内的注释.)

之前我试过通过Safari的SQLite支持来创建客户端的数据库,觉得还应该试试通过HTML5的”Cache Manifest(缓存清单)”来创建离线的Web应用程序.Cache Manifest是一个列出了应用程序所需的所有需要被缓存的资源的文本文件,以便在离线的时候程序一样可以使用.在Cache Manifest中列出的文件会被储存在”Application Cache(应用程序缓存)”里.Application Cache就像浏览器普通缓存,但是却更加强大.只要资源被储存在了Application Cache里,除非相应缓存被清除或者Cache Manifest作废,浏览器永远不会再次从网络请求这个资源.

当我刚开始使用Cache Manifest的时候,我对”离线”方面的兴趣比不上对beasty(译者注:抱歉…没查到这个单词)缓存机制方面的兴趣.只要浏览器发现了Cache Manifest文件,并且得到了你对于它创建离线缓存的许可,浏览器接下来便会在后台开始下载所有需要缓存的资源.如此一来,你只需要点击主页(只是举个例子,不必真的这么做)就可以最终让整个应用程序被缓存下来.并且,一旦应用程序的资源被缓存,对于这个程序的操作,更多的便成了本地的操作,而不是远程的.

为了进行这个HTML5的Cache Manifest试验,我创建了一个非常简单的照片列表页面,并在其中列出了一些链接,以便于查看一些较高分辨率的图片.每一个”查看”页面都是会通过照片的ID动态加载相应图片的ColdFusion页面.列表页面的HTML内容非常简单:

<!---
Use an HTML5 doc-type. This is required for some browsers to
work properly with the offline-cache.
--->
<!DOCTYPE HTML>

<!---
Add a file to the cache manifest. NOTE: Any file that calls
a cache manifest file will be automatically cached, even if
it is in the WHITELIST portion of the cache manifest.
--->
<html manifest="./cache_manifest.cfm">
<head>
<title>Cache Manifest For Offline Pages</title>

<!---
These are the two graphics (logo and startup screen) use
for "app mode" on the iPhone (when the web page is put on
the main screen as its own logo).

NOTE: This part has nothing to do with the cache manifest
stuff - this is strictly related to runnin a website in
"App Mode" on an iPhone. Feel free to remove this entirely
from the example.
--->
<link rel="apple-touch-icon" href="icon.png"/>
<link rel="apple-touch-startup-image" href="home.png" />
</head>
<body>

<h1>
Cache Manifest For Offline Pages
</h1>

<h3>
Pictures of Alisha Morrow
</h3>

<ul>
<cfoutput>

<!---
Notice that we are dynamically generating this
page. It will only be generated on the first
request. After that, this page will be coming out
of the cache.
--->
<cfloop
index="pictureIndex"
from="1"
to="5"
step="1">

<li>
<a href="view.cfm?id=#pictureIndex#"
>View Image #pictureIndex#</a>
</li>

</cfloop>

</cfoutput>
</ul>

<p>
Now:
<cfoutput>
#timeFormat( now() , "hh:mm:ss TT" )#
</cfoutput>
</p>

</body>
</html>

当我们使用Cache Manifest的时候,有两个地方非常重要,首先,因为Cache Manifest是HTML5的一部分,我们需要使用HTML5 doctype:

<!DOCTYPE HTML>

虽然不是所有浏览器都要求这样做(我猜想的话),但为了跨浏览器的兼容性,这样做更好.然后,或许更加重要的东西是我们需要添加一个链接来指向Cache Manifest文件.这条链接是定义在HTML标签里的:

<html manifest="./cache_manifest.cfm">

cache_manifest.cfm文件就是列出了应用程序中所有需要缓存的资源的文件:

Cache Manifest (cache_manifest.cfm)

<!---
Define the Cache Manifest content. I'm doing it this way since
the "CACHE MANIFEST" line needs to be the first line in the file
and storing it in a buffer allows us to TRIM later without having
ugly line breaks.
--->
<cfsavecontent variable="cacheManifest">

<!---
NOTE: Cache Manifest must be the very first thing in this
manifest file.
--->
CACHE MANIFEST

<!---
When a cache manifest is reviewed by the browser, it uses a
complete byte-wise comparison. As such, we can use COMMENTS
to defunk a previously used cache manifest. In this way, we
can use a version-comment to indicate change even when the
file list has not changed.

NOTE: If ANY part of this file is different from the previous
cache manifest, ALL of the files are re-downloaded.
--->
# Cache Manifest Version: 1.3

<!---
Let's list the file that get cached. The URLs to these files
are relative to the cache manifest file (or absolute).
--->
# Core files.
./index.cfm

# iPhone App files.
./icon.png
./home.png

# View Pages. Notice that these can be dynamic pages as long
# as they are valid URLs.
./view.cfm?id=1
./view.cfm?id=2
./view.cfm?id=3
./view.cfm?id=4
./view.cfm?id=5

# Images that get viewed.
./images/1.jpg
./images/2.jpg
./images/3.jpg
./images/4.jpg
./images/5.jpg

</cfsavecontent>


<!--- ----------------------------------------------------- --->
<!--- ----------------------------------------------------- --->


<!---
Let's reset the output and set the appropriate content type.
It is critical that the manifest file be served up as a type
"text/cache-manifest" mime-type.

NOTE: We need to be careful about the whitespace here since
the very first line of the file must contain the phrase,
"CACHE MANIFEST". As such, we must TRIM() the content.
--->
<cfcontent
type="text/cache-manifest"
variable="#toBinary( toBase64( trim( cacheManifest ) ) )#"
/>

在使用Cache Manifest的时候,有一些要点需要明白.第一,”CACHE MANIFEST”这行文字,必须出现在Cache Manifest文件的开头.第二,文件的类型必须被定义为MIME类型,”text/cache-manifest”.第三,整个Cache Manifest文件是通过每个字节来区分版本的.这第三点的意思就是说,Cache Manifest文件中任何位置的变动,包括注释内容(#),都会使原来的Cache Manifest作废.此时,整个列表中需要被缓存的资源都会被重新下载.

就像在CSS文件中一样,Cache Manifest中列出的资源路径既可以是完整的,也可以是相对这个Cache Manifest文件的.因为我们缓存的是动态页面,这些动态页面按说应该独立地列在Cache Manifest文件里(译者注:可能意思是,举个例子,有时动态页面需要更新缓存,而图片不变,这是如果动态页面的Cache Manifest文件和图片的是一个文件,便会使整个列表,也即包括图片被重新下载).还有其他的一些办法来做到这点,但是仅对于我的试验来说,这是最简单的做法.

列表中的”查看”页面除了动态显示与获得的ID相应的图片以外,什么也没做.

view.cfm

<!--- Param the image ID that we are going to view. --->
<cfparam name="url.id" type="numeric" />


<!---
Use an HTML5 doc-type. This is required for some browsers to
work properly with the offline-cache.
--->
<!DOCTYPE HTML>

<!---
Add a file to the cache manifest. NOTE: Any file that calls
a cache manifest file will be automatically cached, even if
it is in the WHITELIST portion of the cache manifest.
--->
<html manifest="./cache_manifest.cfm">
<head>
<title>View Image</title>
</head>
<body>

<h1>
View Image
</h1>

<p>
&laquo; <a href="./index.cfm">Back to List</a>
</p>

<p>
<cfoutput>
<img src="./images/#url.id#.jpg" width="300" />
</cfoutput>
</p>

</body>
</html>

我在查看页面中也加入了Cache Manifest的链接;虽然我相信它并没有被浏览器请求.只要用户首先打开的是列表页面,Cache Manifest文件便会被下载,并且查看页面应该被自动缓存了.我在这里也加上这个,只是单纯地为了保险(译者注:原文为for good measure,不知道能不能我这样翻译).

在列表页面中,你可能已经注意到了一些奇怪的LINK标签,这些LINK标签是为苹果的iPhone设计的Web应用在”App Mode(应用程序模式)”用来定义其图标和启动界面图形的.”App Mode”是当页面URL被添加到了iPhone的Home Screen(主页面)时实现的全屏的模式.这些Link标签与Cache Manifest没有关系;但是,它们能说明我进行HTML5在这一块的探索的原因-为iPhone创建可以在本地运行(译者注:原文为native-esque,没查到)的Web应用程序.

Cache Manifest似乎是HTML5的一个非常酷特征,这些例子能够在Firefox,Safari和我的iPhone上运行(没有尝试过其他浏览器).我并没有在桌面Safari的研究上下很多的功夫,但是或许它能在Firefox的离线模式和iPhone的飞行模式下使用已经非常惊人了.就像我之前所说的,我最终想要进行这个研究,是为了让我的Dig Deep Fitness web application在iPhone上像本地应用程序那样运行.

注意:当我刚开始尝试使用Cache Manifest时,为了让离线缓存被识别,费了很大的力气.两天的时间我一直在检查我的拼写和无效链接.后来我重新启动了Firefox,终于得到了一点安慰(译者注:原文blam,没查到,Google了下,貌似有类似的意思)-它开始工作了.所以,如果第一次没有作用,你或许需要重新启动一下浏览器.