离线 Web 应用

网络是任何 Web 应用的关键组成部分,无论它是用于下载 JavaScript、CSS 和 HTML 源文件以及相关资源(图像、视频等),还是用于访问 Web 服务(XMLHttpRequest 和<forms>)。

但是,为 Web 应用提供离线支持对用户来说非常有用。例如,想象一个 Web 邮件应用,即使在用户断开连接时,也允许用户阅读其收件箱中的邮件并撰写新邮件。

用于支持离线 Web 应用的机制还可以用于通过将数据存储在缓存中来提高应用的性能,或者在用户会话之间以及重新加载和恢复页面时使数据保持持久性。

演示:待办事项列表管理器

要查看离线 Web 应用的实际操作,请观看 Vivien Nicolas 的演示(OGVMP4),该演示展示了在运行 Firefox 的 N900 上在线和离线运行的待办事项列表管理器。

您还可以查看该应用的在线演示

创建您自己的离线应用

要使 Web 应用能够离线工作,您需要考虑以下三点

让我们看看如何使用这些组件。

存储:持久性数据

DOM 存储允许您在浏览器会话之间存储数据,在选项卡之间共享数据,并防止数据丢失(例如来自页面重新加载或浏览器重新启动)。数据以字符串(例如 JSON 格式的 JavaScript 对象)的形式存储在 Storage 对象中。

有两种存储全局对象:sessionStoragelocalStorage

  • sessionStorage维护一个在页面会话期间可用的存储区域。页面会话持续到浏览器打开的时间,并在页面重新加载和恢复期间保持不变。在新选项卡或窗口中打开页面会导致启动新的会话。
  • localStorage维护一个可用于长时间保存数据(例如,跨多个页面和浏览器会话)的存储区域。当用户关闭浏览器或关闭计算机时,它不会被销毁。

localStorage 和 sessionStorage 都使用以下 API

window.localStorage and window.sessionStorage {
  long length; // Number of items stored
  string key(long index); // Name of the key at index
  string getItem(string key); // Get value of the key
  void setItem(string key, string data); // Add a new key with value data
  void removeItem(string key); // Remove the item key
  void clear(); // Clear the storage
};

以下是一个显示如何存储和读取字符串的示例

// save the string
function saveStatusLocally(txt) {
  window.localStorage.setItem("status", txt);
}

// read the string
function readStatus() {
   return window.localStorage.getItem("status");
}

请注意,存储属性仅限于 HTML5 来源(方案 + 主机名 + 非标准端口)。这意味着来自 http://foo.com 的 window.localStorage 与来自 http://bar.com 的 window.localStorage 是不同的实例。例如,http://google.com 无法访问 http://yahoo.com 的存储。

我们是否离线?

在存储数据之前,您可能希望知道用户是否在线。例如,这对于确定是在本地(客户端)存储值还是将其发送到服务器很有用。

使用navigator.onLine属性检查用户是否在线。
此外,您可以通过侦听窗口元素的onlineoffline事件来获取任何连接更改的通知。

这是一段非常简单的 JavaScript 代码,它将您的状态发送到服务器(类似于 Twitter)。

  • 如果您设置了状态并且在线,它会发送状态。
  • 如果您设置了状态并且离线,它会存储您的状态。
  • 如果您上线并且有存储的状态,它会发送存储的状态。
  • 如果您加载页面,并且在线且有存储的状态,它会发送存储的状态。
function whatIsYourCurrentStatus() {
  var status = window.prompt("What is your current status?");
  if (!status) return;
  if (navigator.onLine) {
    sendToServer(status);
  } else {
    saveStatusLocally(status);
  }
}

function sendLocalStatus() {
  var status = readStatus();
  if (status) {
    sendToServer(status);
    window.localStorage.removeItem("status");
  }
}


window.addEventListener("load", function() {
   if (navigator.onLine) {
     sendLocalStatus();
   }
}, true);

window.addEventListener("online", function() {
  sendLocalStatus();
}, true);

window.addEventListener("offline", function() {
  alert("You're now offline. If you update your status, it will be sent when you go back online");
}, true);

离线资源:缓存清单

离线时,用户的浏览器无法访问服务器以获取可能需要的任何文件。您不能总是依赖浏览器的缓存包含所需的资源,因为用户可能已清空了缓存,例如。这就是为什么您需要明确定义哪些文件必须存储,以便在用户离线时所有所需的文件和资源都可用:HTML、CSS、JavaScript 文件和其他资源,如图像和视频。

清单文件在 HTML 中指定,并包含应用应为离线使用而缓存的文件的明确列表。


这是一个清单文件内容的示例

CACHE MANIFEST
fonts/MarketingScript.ttf
css/main.css
css/fonts.css
img/face.gif
js/main.js
index.xhtml

清单文件的 MIME 类型必须是:text/cache-manifest

查看文档以了解有关清单文件格式和缓存行为的更多详细信息。

总结

在使应用能够离线工作时,您应该记住的关键组件是将用户输入存储在 localStorage 中,创建一个缓存清单文件,以及监控连接更改

访问Mozilla 开发者中心以获取完整文档。

关于 Paul Rouget

Paul 是一位 Firefox 开发者。

更多 Paul Rouget 的文章…


34 条评论

  1. Paul Rouget

    还有一件事
    我们讨论了 local/sessionStorage。我们*尚未*支持任何 databaseStorage(例如 Webkit 使用 sqlite 的方式),因为我们认为我们需要一些不同的、更简单的(由 Oracle 的 Nikunj Mehta 编辑的索引顺序存储 API)。请在此处查看更多详细信息:http://us1.campaign-archive.com/?u=168bf22f976f5a68fe5770d19&id=6c2d73c957#standards

    2010 年 1 月 7 日 12:45

  2. Chris

    太棒了,我希望所有浏览器都能尽快支持它 :)

    2010 年 1 月 7 日 21:49

  3. Eevee

    我怀念那些运行程序和读取文件无需互联网就不是一项令人印象深刻的技术壮举的日子。:(

    2010 年 1 月 7 日 22:33

    1. zahra

      我也是

      2011 年 1 月 12 日 08:02

  4. frank goossens

    Firefox 中缺乏“结构化”存储——尽管不希望使用 sqlite 进行数据库存储背后的理由是正确的——令人沮丧,尤其是在预计 Chrome 和 Opera 将提供 webdb 支持的情况下。FF 中“索引顺序存储 API”的包含是否有任何路线图?

    话虽如此;离线应用的最大问题是跨浏览器兼容性。我一直在开发一个跨浏览器离线启用的 Web 应用,该应用可以使用结构化方式存储数据,使用persistjs(一个抽象对 localStorage、webdb、IE 用户数据行为、Gears、Flash 等的访问的 JavaScript 库)来存储 JSON 格式的数组/对象,以及应用缓存(同时使用 HTML5 和 Gears 本地服务器)。您可以在此处查看结果 TrappistDB

    2010 年 1 月 8 日 00:33

  5. Jon Rimmer

    localStorage 的设计是否存在问题?我读到了一些东西表明在多进程浏览器中无法以高性能的方式实现当前规范。这方面的最新情况如何?

    2010 年 1 月 8 日 03:23

  6. matt

    在这些不可靠的云的早期阶段了解这一点真是太好了

    2010 年 1 月 8 日 04:51

  7. Natanael L

    如果可以使用 torrent 共享大型文件,例如在 YouTube 上,那就太好了 :)

    2010 年 1 月 8 日 06:30

  8. Cedric Dugas

    我希望浏览器供应商能够实现相同的数据库存储……要在 Safari 和 Firefox 上使其工作将是一团糟..

    2010 年 1 月 8 日 08:33

  9. […] Hacks 开发了一个演示应用程序,使我们能够在浏览器中拥有一个任务列表,您可以查看它 […]

    2010 年 1 月 8 日 17:10

  10. […] Hacks 开发了一个演示应用程序,使我们能够在浏览器中拥有一个任务列表,您可以查看它 […]

    2010 年 1 月 8 日 18:01

  11. nemo

    Cedric,localStorage 也适用于 Webkit 和 IE8。
    在解决 sqlite 问题之前,似乎最好只使用它。这并不是一团糟。

    即使您最终可以在 Firefox 和 Safari 中执行 SQL 查询,您可能仍然需要等待 IE。

    2010 年 1 月 9 日 20:11

  12. yannski

    我们的用户对我们的离线应用(我们开发了一个小型产品生命周期管理工具)最希望获得的功能之一是能够从同步过程中获得反馈,例如“正在下载 3/325 个文档”。最初使用 Gears 时这是不可能的,但他们最终实现了它。现在,FF 中的原生离线“模式”似乎无法做到这一点。或者我没有找到 applicationCache JavaScript 对象的正确文档……例如,我无法访问https://mdn.org.cn/en/nsIDOMOfflineResourceList中描述的“items”属性

    也许您可以提供一些提示…

    2010 年 1 月 12 日 07:11

  13. Paul Rouget

    @yannski MDC API 是错误的。“moz”前缀丢失了(例如 mozItem)。我们会尽快修复它。

    您可以在此处查看正确的 API
    http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/offline/nsIDOMOfflineResourceList.idl

    2010 年 1 月 15 日 08:05

  14. yannski

    好吧,使用 Firefox 3.5,window.applicationCache.mozItems 似乎始终为空(或者我不理解如何使用它)。一些代码示例将非常棒…

    2010 年 1 月 17 日 15:44

  15. Pete

    使用https://addons.mozilla.org/de/firefox/addon/70769可以获得类似 Webkit 的数据库存储

    2010 年 2 月 18 日 12:50

  16. Aris Micro

    但是,如果您使用 file:// 方案(而不是http://),即如果您离线并双击本地 .html 文件,则 localStorage 无法工作。

    2010 年 2 月 21 日 18:49

  17. Omkar Kandarpa

    你好,

    您可以使用 applicationCache 对象的 downloading 和 progress 事件访问缓存的当前状态以及挂起文件的数量。

    2010 年 6 月 1 日 01:21

  18. […] 离线 Web 应用,2010 年 1 月 7 日,Paul […]

    2010 年 6 月 30 日 18:32

  19. […] HTML5 应用程序缓存:这允许您创建即使在浏览器未连接到 Internet 时也可以使用的应用程序。它通过将整个应用程序存储在浏览器中并提供对在线和离线事件的访问来实现这一点,从而使应用程序能够知道何时需要与服务器重新同步。 […]

    2010 年 7 月 7 日 09:22

  20. Patrick

    考虑为 HTML5 数据库实现 ORM(http://impel.simulacre.org/)。

    2010 年 7 月 28 日 04:49

  21. Günter

    开始编写一个仅在本地浏览器模式下使用的 ICS/iCal“应用程序”,并且目标是仅使用 HTML/CSS/JS。
    这需要访问与本地文件系统一起存储的 ics 文件(也需要与其他应用程序(如 Lightning 等)一起使用)。

    目前,对于本地存储访问,我正在使用 jQuery.twFile.js,它基本上使用一些 Moz Components.classes。


    如何修改这个概念,以便使用HTML5存储,使其可以在任何HTML5平台上使用?
    是否有任何进一步的信息/讨论的线索?

    2010年10月31日 05:28

  22. Pedro Morais

    我写了一篇博文,介绍了我们如何使我们的时间跟踪网络应用程序离线工作。
    这可能很有用,因为它是一个真实的例子。
    http://blog.bitrzr.com/2010/10/html5-offline-webapps-practical-example.html

    2010年11月28日 09:38

  23. Mani

    也许是一篇好文章,我不知道……我在看到一个视频下载后感到恼火,而且我无法停止它。而且我知道我正在为这种带宽付费,却无助地看着视频加载。

    这可能是HTML5的一个缺点——如果我们使用的是昂贵的流量套餐,我们需要停止视频下载。现在我需要一个插件来阻止html5视频。将来,我们将不可避免地看到广告加载并消耗带宽,flashblock曾经非常好。

    致作者:在你发布那个自动加载的愚蠢的HTML5视频之前,你有没有想过访客的感受?并不是每个人都从他们无限的家庭宽带访问你的页面。

    2011年5月22日 20:49

    1. louisremi

      您可以在浏览器中打开about:config,阅读警告消息并接受它,然后右键单击列表中的任意位置,“新建”>“整数”
      然后为首选项命名为“media.preload.default”,并选择1作为值。
      重复使用名称“media.preload.auto”,并选择2作为值
      搞定啦 :-)

      2011年5月23日 08:42

      1. Mani

        太棒了,非常感谢!!!

        我收回我最初的评论,那是没有必要的,我应该在发布之前进行探索。对此表示歉意。

        您知道谷歌浏览器是否有类似的方法吗?无论如何,在找到Chrome的方法之前,Firefox将是我的默认浏览器。

        再次感谢 :-)

        2011年5月23日 08:54

  24. […] https://hacks.mozilla.ac.cn/2010/01/offline-web-applications/ […]

    2011年6月2日 00:45

  25. […] Mozilla Hacks: 离线网页应用程序 […]

    2011年6月19日 22:06

  26. […] Mozilla Hacks: Offline Web Applications […]

    2011年7月10日 06:12

  27. […] SitePointStandardists Estelle Weyl’s take on offline web appsMore fromthe folks at Mozilla on building offline web appsOpera Developers Network on building offline web apps.Critiques and gotchasas we know, all is not […]

    2011年7月11日 04:05

  28. […] More fromthe folks at Mozilla on building offline web apps […]

    2011年7月19日 12:57

  29. […] Mozilla Hacks: 离线网页应用程序 […]

    2011年8月23日 00:53

  30. Yv.R

    您好,首先感谢您的帖子。只是想问您几个问题。我正在使用离线模式和appcache制作一些网络应用程序……它可以在Chrome浏览器或一些移动浏览器(如海豚)中完美运行……但仍然无法在Firefox中运行。我从Firefox 3.6.26(我的客户使用)开始,然后迁移到最新的18.0.2,但它仍然无法运行。以下是最重要的文件

    – htaccess
    AddType text/cache-manifest .appcache

    – cache.appcache
    # v3.3..4

    CACHE

    index.html
    page2.html
    img.png
    off.html

    SETTINGS
    prefer-online

    FALLBACK
    / /off.html

    NETWORK
    *

    – 最后是主文件中的行

    您是否遇到过此问题?

    2013年2月12日 07:56

    1. IMEVER

      也许您的 – cache.appcache文件应该以“CACHE MANIFEST”开头

      2013年2月19日 03:04

本文评论已关闭。