应用缓存使用入门指南

应用缓存使用入门指南

Eric Bidelman

简介

让基于 Web 的应用能够在离线状态下访问变得越来越重要。是的,所有浏览器都可以在收到指示后长时间缓存网页和资源,但浏览器可以随时将个别项从缓存中移出,以腾出空间来存放其他内容。HTML5 通过 ApplicationCache 接口解决了离线状态的一些烦恼。使用缓存接口可为您的应用带来以下三项优势:

离线浏览 - 用户可以在离线状态下浏览您的整个网站

速度 - 资源直接从磁盘获取,无需访问网络。

弹性 - 如果您的网站因“维护”而宕机(例如,有人意外破坏了所有内容),您的用户将获得离线体验

借助应用缓存(或 AppCache),开发者可以指定浏览器应缓存哪些文件,并将这些文件提供给离线用户。您的应用将正常加载并正常运行,即使用户在离线状态下按下刷新按钮也是如此。

缓存清单文件

缓存清单文件是一个简单的文本文件,其中列出了浏览器应缓存以供离线访问的资源。

引用清单文件

如需为应用启用应用缓存,请在文档的 html 标记中添加清单属性:

...

您应在要缓存的 Web 应用的每个网页中添加 manifest 属性。如果网页不包含 manifest 属性,浏览器不会将其缓存(除非该属性在清单文件本身中明确列出)。这意味着,用户导航到的任何包含 manifest 的页面都会被隐式添加到应用缓存中。因此,您无需在清单中列出每个网页。如果某个网页指向清单,则无法阻止系统缓存此网页。

注意 :系统会将“/page-url/”“/page-url/?something”“/page-url/?something-else”视为不同的网页。如果它们链接到清单,则所有这些资源都会被隐式单独缓存。鉴于这一点以及其他注意事项,AppCache 最适合用于只有一个网址的应用。

您可以在 Chrome 中访问 about://://appcache-internals/,查看由应用缓存控制的网址。在这里,您可以清除缓存并查看条目。Firefox 中提供了类似的开发者工具。

manifest 属性可以指向绝对网址或相对路径,但绝对网址必须与 Web 应用位于同一源下。清单文件可以采用任何文件扩展名,但需要使用正确的 MIME 类型进行传送(见下文)。

...

清单文件必须使用 text/cache-manifest MIME 类型提供。您可能需要向网络服务器或 .htaccess 配置添加自定义文件类型。

例如,如需在 Apache 中提供此 MIME 类型,请将以下代码行添加到配置文件中:

AddType text/cache-manifest .appcache

或者,在 Google App Engine 的 app.yaml 文件中:

- url: /mystaticdir/(.*\.appcache)

static_files: mystaticdir/\1

mime_type: text/cache-manifest

upload: mystaticdir/(.*\.appcache)

此要求已于一段时间前从规范中移除,最新版本的 Chrome、Safari 和 Firefox 不再需要此要求,但您需要 mime 类型才能在旧版浏览器和 IE11 中正常运行。

清单文件的结构

清单是您通过 html 元素上的清单属性链接到的单独文件。一个简单的清单如下所示:

CACHE MANIFEST

index.html

stylesheet.css

images/logo.png

scripts/main.js

http://cdn.example.com/scripts/main.js

此示例将在指定此清单文件的网页上缓存四个文件。

请注意以下几点:

CACHE MANIFEST 字符串是第一行,且为必填项。

文件可以来自其他网域

某些浏览器会对应用可用的存储空间配额施加限制。例如,在 Chrome 中,AppCache 使用其他离线 API 可以共享的临时存储空间共享池。如果您要为 Chrome 应用商店编写应用,使用 unlimitedStorage 即可解除此限制。

如果清单本身返回 404 或 410,则会删除缓存。

如果清单或其中指定的资源下载失败,则整个缓存更新流程都会失败。如果失败,浏览器将继续使用旧版应用缓存。

我们来看一个更复杂的示例:

CACHE MANIFEST

# 2010-06-18:v2

# Explicitly cached 'master entries'.

CACHE:

/favicon.ico

index.html

stylesheet.css

images/logo.png

scripts/main.js

# Resources that require the user to be online.

NETWORK:

*

# static.html will be served if main.py is inaccessible

# offline.jpg will be served in place of all images in images/large/

# offline.html will be served in place of all other .html files

FALLBACK:

/main.py /static.html

images/large/ images/offline.jpg

以“#”开头的行是注释行,但也可以用于其他用途。

只有在应用的清单文件发生变化时,其缓存才会更新。例如,如果您修改图片资源或更改 JavaScript 函数,这些更改不会重新缓存。您必须修改清单文件本身,以通知浏览器刷新缓存的文件。

避免使用不断更新的时间戳或随机字符串来强制每次更新。在更新期间,系统会检查两次清单,一次在开始时,一次在更新所有缓存文件后。如果清单在更新期间发生了变化,则浏览器可能会从一个版本提取一些文件,从另一个版本提取其他文件,因此不会应用缓存,并会稍后重试。

虽然缓存会更新,但在网页刷新之前,浏览器不会使用这些文件,因为更新是在从当前缓存版本加载网页后进行的。

清单可以包含三个不同的部分:CACHE、NETWORK 和 FALLBACK。

CACHE:

这是条目的默认部分。此标头下列出的文件(或 CACHE MANIFEST 后面紧跟的文件)在首次下载后会被明确缓存。NETWORK:

如果此部分列出的文件不在缓存中,则可能会从网络中获取,否则系统不会使用网络,即使用户处于在线状态也是如此。您可以在此处将特定网址列入许可名单,也可以直接输入“”,以允许所有网址。大多数网站都需要输入“”。

FALLBACK:

一个可选部分,用于指定在无法访问资源时显示的回退页。第一个 URI 是资源,第二个 URI 是网络请求失败或出错时使用的回退 URI。这两个 URI 都必须与清单文件来自同一来源。您可以捕获特定网址,也可以捕获网址前缀。“images/large/”将捕获“images/large/whatever/img.jpg”等网址中的失败情况。

注意: 这些部分可以按任意顺序列出,并且每个部分在单个清单中可以出现多次。

以下清单定义了一个“万能网页”(offline.html),当用户在离线状态下尝试访问网站根目录时,系统会显示该网页。它还声明所有其他资源(例如远程网站上的资源)都需要连接到互联网。

CACHE MANIFEST

# 2010-06-18:v3

# Explicitly cached entries

index.html

css/style.css

# offline.html will be displayed if the user is offline

FALLBACK:

/ /offline.html

# All other resources (e.g. sites) require the user to be online.

NETWORK:

*

# Additional resources to cache

CACHE:

images/logo1.png

images/logo2.png

images/logo3.png

注意 :系统会自动缓存引用清单文件的 HTML 文件。您无需在清单中添加此标头,但我们建议您这样做。

注意: 缓存清单会覆盖通过 SSL 提供的网页上的 HTTP 缓存标头和缓存限制。因此,通过 https 提供的网页可以离线使用。

更新缓存

应用离线后,会一直处于缓存状态,直到发生以下情况之一:

用户清除其浏览器中与您的网站相关的数据存储空间。

清单文件已修改。注意:更新清单中列出的文件并不意味着浏览器会重新缓存该资源。必须更改清单文件本身。

缓存状态

window.applicationCache 对象是您以编程方式访问浏览器应用缓存的方式。其 status 属性对于检查缓存的当前状态非常有用:

var appCache = window.applicationCache;

switch (appCache.status) {

case appCache.UNCACHED: // UNCACHED == 0

return 'UNCACHED';

break;

case appCache.IDLE: // IDLE == 1

return 'IDLE';

break;

case appCache.CHECKING: // CHECKING == 2

return 'CHECKING';

break;

case appCache.DOWNLOADING: // DOWNLOADING == 3

return 'DOWNLOADING';

break;

case appCache.UPDATEREADY: // UPDATEREADY == 4

return 'UPDATEREADY';

break;

case appCache.OBSOLETE: // OBSOLETE == 5

return 'OBSOLETE';

break;

default:

return 'UKNOWN CACHE STATUS';

break;

};

如需以编程方式检查清单的更新,请先调用 applicationCache.update()。这将尝试更新用户的缓存(这需要清单文件发生更改)。最后,当 applicationCache.status 处于 UPDATEREADY 状态时,调用 applicationCache.swapCache() 会将旧缓存换成新缓存。

var appCache = window.applicationCache;

appCache.update(); // Attempt to update the user's cache.

...

if (appCache.status == window.applicationCache.UPDATEREADY) {

appCache.swapCache(); // The fetch was successful, swap in the new cache.

}

注意: 以这种方式使用 update() 和 swapCache() 意味着新缓存将用于后续下载,但用户此时可能已下载网页和所有资源,因此这些文件不会自动重新加载。您需要刷新页面以获取最新版本的页面和资源,而无需调用 swapCache()

好消息是,您可以将此操作自动化。如需将用户更新到您网站的最新版本,请设置监听器以监控网页加载时的 updateready 事件:

// Check if a new cache is available on page load.

window.addEventListener('load', function(e) {

window.applicationCache.addEventListener('updateready', function(e) {

if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {

// Browser downloaded a new app cache.

if (confirm('A new version of this site is available. Load it?')) {

window.location.reload();

}

} else {

// Manifest didn't changed. Nothing new to server.

}

}, false);

}, false);

AppCache 事件

正如您所料,系统会公开其他事件来监控缓存的状态。浏览器会针对下载进度、更新应用缓存和错误情况等事件触发事件。以下代码段为每种类型的缓存事件设置了事件监听器:

function handleCacheEvent(e) {

//...

}

function handleCacheError(e) {

alert('Error: Cache failed to update!');

};

// Fired after the first cache of the manifest.

appCache.addEventListener('cached', handleCacheEvent, false);

// Checking for an update. Always the first event fired in the sequence.

appCache.addEventListener('checking', handleCacheEvent, false);

// An update was found. The browser is fetching resources.

appCache.addEventListener('downloading', handleCacheEvent, false);

// The manifest returns 404 or 410, the download failed,

// or the manifest changed while the download was in progress.

appCache.addEventListener('error', handleCacheError, false);

// Fired after the first download of the manifest.

appCache.addEventListener('noupdate', handleCacheEvent, false);

// Fired if the manifest file returns a 404 or 410.

// This results in the application cache being deleted.

appCache.addEventListener('obsolete', handleCacheEvent, false);

// Fired for each resource listed in the manifest as it is being fetched.

appCache.addEventListener('progress', handleCacheEvent, false);

// Fired when the manifest resources have been newly redownloaded.

appCache.addEventListener('updateready', handleCacheEvent, false);

如果清单文件或其中指定的资源下载失败,则整个更新都会失败。在发生此类失败的情况下,浏览器将继续使用旧版应用缓存。

参考

ApplicationCache API 规范

应用缓存很难搞定 - 介绍了 AppCache 的注意事项和问题。

相关推荐

在 Mac 上截屏
365betappios

在 Mac 上截屏

📅 07-07 👁️ 6961
《蚂蚁》伊索寓言故事及寓意道理
365bet亚洲版登陆

《蚂蚁》伊索寓言故事及寓意道理

📅 07-06 👁️ 4877
十大最受欢迎的西餐特色菜排名 西餐最好吃的10款美味菜肴盘点→MAIGOO生活榜
缮夤密码说 |“读心术”是2号人的天赋
365betappios

缮夤密码说 |“读心术”是2号人的天赋

📅 06-27 👁️ 4379
前的成语
365bet亚洲版登陆

前的成语

📅 06-30 👁️ 3321
扇子的拼音解释及造句
365betappios

扇子的拼音解释及造句

📅 07-06 👁️ 6942