返回介绍

离线 Web 程序

发布于 2025-01-01 12:18:10 字数 4693 浏览 0 评论 0 收藏 0

什么是离线 web 程序?咋一看起来,它很像一个矛盾。web 页面就是你下载下来之后渲染的。下载暗示着必须联网。那么当你离线的时候怎么下载呢?显然,你不能。但是你可以连线的时候下载好。这就是 HTML5 离线程序的工作原理。

最简单的一种离线 web 程序包括一系列 URL—— HTML、CSS、JavaScript、图像,以及其他类型的资源。在线 web 程序的主页有个文件指定这个列表,称为 manifest 清单文件。这仅仅是一个放置在 web 服务器的文本文件。实现了 HTML5 离线程序功能的浏览器从 manifest 文件读取 URL 列表,下载所有资源,将它们缓存到本地,并且能够在它们被修改的时候自动更新这些缓存文件。当你离线访问 web 程序时,浏览器自动转换到本地缓存的版本。

现在,大部分工作都交给你了,web 开发者。DOM 中有一个标记可以告诉你现在是在线还是离线。当你的离线状态发生改变的时候(这一分钟你离线,下一分钟你就在线了,或者相反的情况下),浏览器会发出一些事件。这些事件还是很多的。如果应用程序需要创建数据或者保存状态,那么,在离线状态下是否需要将数据存储到本地,然后在连接到服务器时自动与远程服务器同步,就取决于你的实现了。换句话说,HTML5 可以让你的 web 程序离线运行,而你的程序离线的时候到底如何运行则取决于你。

IEFirefoxSafariChromeOperaiPhoneAndroid
3.5+4.0+5.0+10.6+2.1+2.0+

缓存清单文件

离线 web 程序需要一个缓存的清单文件。什么是清单文件?它是你的 web 程序所需要的所有资源的一个列表,在你离线访问程序的时候可能会用到这些资源。为了加快下载速度、缓存这些资源,你需要将这些资源在清单文件中指明。我们需要在 <html> 中使用 manifest 属性。

<!DOCTYPE HTML>
<html manifest="/cache.manifest">
<body>
...
</body>
</html>

缓存清单文件可以在 web 服务器的任何位置,但是其内容类型必须是 text/cache-manifest。如果你的服务器是基于 Apache 的,那么可以在 web 站点根目录的 .htaccess 文件中使用 AddType 指令添加:

AddType text/cache-manifest .manifest

然后确保清单文件的文件名以 .manifest 结束。如果你使用不同的 web 服务器或者 Apache 的不同配置,请自行查阅服务器的文档,应该是在管理 Content-Type 头这么一节中。

FAQ

Q: 我的 web 程序有好几页,那么我需要在每一页都加入这个 manifest 属性吗?还是仅仅在首页加入?

A: 你的程序的每一页都需要加入 manifest 属性,用以指出整个程序的清单。

好了,现在你的每一个 HTML 页面都指定了一个缓存清单文件,并且该文件也有了合适的 Content-Type 头。那么,这个文件我们该如何编写呢?这才是最有趣的地方。

缓存清单文件第一行是这样的:

CACHE MANIFEST

在那之后,所有的清单文件都被分为三部分:“显式”部分(explicit)、“回调”部分(fallback)和“在线白名单”(online whitelist)。每一部分都有占据单独一行的头。如果清单文件没有任何头,则所有资源都默认是在 explicit 部分。” 提醒一点,不要纠结于这些名词,以免你会头疼。

下面是一个合法的清单文件。它列出了三个资源:一个 CSS 文件,一个 JavaScript 文件和一个 JPEG 图片。

CACHE MANIFEST
/clock.css
/clock.js
/clock-face.jpg

这个清单文件没有分块的头信息,因此所有列出的资源都属于 explicit 部分。explicit 部分的资源将被下载下来,缓存到本地,并且在程序离线的时候使用。因此,在加载这个清单文件之后,浏览器就会将 clock.css、clock.js 和 clock-face.jpg 从 web 服务器根目录下载下来。当你的网络断掉后,重新刷新页面,这些资源将继续可以使用。

FAQ

Q: 我需要在缓存清单文件中列出 HTML 页面吗?

A: 是,也不是。如果你的整个 web 应用程序仅有一个页面,只要确保这个页面使用了 manifest 属性指定了清单文件即可。当你浏览一个指定了 manifest 属性的 HTML 页面时,这个页面将自动作为 web 程序的一部分,所以你无需在清单文件中列出来。但是,如果你的程序有多个页面,你需要在清单文件中列出所有 HTML 页面,否则浏览器不知道哪些页面应该被下载并且缓存下来。

Network 块

下面是一个比较复杂的例子。假设你想让你的时钟程序追踪访问者,使用 <img src> 指定的一段 tracking.cgi 脚本。将这个资源缓存下来显然没什么用处,因为本地使用的话并不能起到追踪的作用。所以,这个资源不应该被缓存起来,也不能离线使用。下面我们告诉你该怎么做:

CACHE MANIFEST
NETWORK:
/tracking.cgi
CACHE:
/clock.css
/clock.js
/clock-face.jpg

这个缓存清单文件包含有块的声明。NETWORK 这行标志着 online whitelist 块的开始。这个块中列出的资源不应该被缓存,也不能够离线使用。(试图离线加载会引发一个错误。)CACHE 这行标志着 explicit 块的开始。这个清单的剩下部分同前面是一样的。这三个资源都将被缓存,并且可以用于离线使用。

Fallback 块

清单文件还有一种块类型:fallback 块。在 fallback 中,你可以定义那些不能被缓存,或者没有缓存成功的资源的替代资源。HTML5 标准提供了一个例子:

CACHE MANIFEST
FALLBACK:
/ /offline.html
NETWORK:
*

这是在做什么?首先,想象一个拥有几百万页面的网站,例如 Wikipedia。你不可能将整个站点都下载下来,即使你想这么干。不过,你可以让某一部分可以离线使用。但你怎么指定哪些页面被缓存呢?看看这么做怎么样:在一个假想的 Wikipedia 站点上,每一个你浏览过的页面都可以被下载并且被缓存。这将包含你浏览过的每一个内容页面,每一个讨论页面,每一个编辑页面。

这就是这个清单文件做的事。假设 Wikipedia 上每一个 HTML 页面(内容页、讨论页、编辑页和历史页面)都指定了这个清单文件。当你访问这个清单文件指定的任何页面的时候,浏览器会说,“这个页面时离线 web 程序的一部分,这是我曾经下载过的吗?”如果浏览器从来没有下载过这个清单文件,它将创建一个新的离线 “appcache”(也就是 application cache),将清单文件指定的所有资源都下载下来,但后将当前页面加入到 appcache。如果浏览器已经下载过这个清单文件,它仅仅将当前页面加入已有的 appcache。不管哪种方法,你访问的页面都被添加到了 appcache。这是十分重要的一点。这意味着你可以有一个能够“迟缓”添加页面的离线 web 应用程序。你不需要将所有单独的 HTML 页面都添加到清单文件中。

下面看看 fallback 块。清单文件中的 fallback 块只有一行。这一行的第一部分(空格之前的部分)不是一个 URL。它只是一个 URL 模式。一个单独的字符 / 可以匹配你的站点的任何页面,不仅仅是首页。当你离线访问一个页面的时候,浏览器将从 appcache 中查找、如果找到(这是因为你曾经在线访问过它,该页面被隐式添加到了 appcache 中),则显示这个页面的缓存;如果没有,浏览器也不会显示错误,而是显示 /offline.html 页面,这是由 fallback 块的这行的第二部分指定的。

最后,我们再看看 network 块。network 块也只有一行,这一行仅有一个字符 *。这个字符在 network 块有特殊的含义。它被称为“在线白名单通配符 online whitelist wildcard flag”。它说明,只要你有 web 连接,所有不在 appcache 中的资源都应该从原始 web 地址下载。这对于一个“开放式结尾”的 web 应用程序尤其重要。它意味着,当你浏览这个假想的能够离线访问的 Wikipedia 的时候,浏览器可以像其他网站一样获取图片、视频或者其它嵌入资源,甚至是不同域名下的。(这在大型网站中很常见,甚至它们根本不是离线 web 程序的一部分。HTML 页面可以在本地缓存,而图片和视频则需要通过另外一个域名的 CDN 获取。)如果没有通配符,我们的离线 Wikipedia 在在线浏览的时候就会显得很奇怪——不能加载任何不在同一服务器的图片或者视频!

这个例子是完备的吗?不是。Wikipedia 不仅仅是 HTML 文件。它还在每一个 HTML 页面使用了 CSS、JavaScript 和各种图片。这些所有资源都需要显示地被列在清单文件的 CACHE 块中,以便让这些页面能够正确地离线显示。但是,fallback 块则指出一个“开放式结尾”的离线 web 程序,能够让没有在清单文件中列出的资源正确使用。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文