聊一聊H5应用缓存-Manifest

原文: 聊一聊H5应用缓存-Manifestcss

导读

Manifest 是 H5提供的一种应用缓存机制, 基于它web应用能够实现离线访问(offline cache). 为此, 浏览器还提供了应用缓存的api--applicationCache. 虽然manifest的技术已被web标准废弃, 但这不影响咱们尝试去了解它. 也正是由于manifest的应用缓存机制如此诱人, 饿了么 和 office 365邮箱等都还在使用着它!html

描述

对manifest熟悉的同窗能够跳过此节.html5

鉴于manifest应用缓存的技术, 咱们能够作到:ios

  • 离线访问: 即便服务器挂了, 或者没有网络, 用户依然能够正常浏览网页内容.git

  • 访问更快: 数据存在于本地, 省去了浏览器发起http请求的时间, 所以访问更快, 移动端效果更为明显.github

  • 下降负载: 浏览器只在manifest文件改动时才去服务器下载须要缓存的资源, 大大下降了服务器负载.web

manifest缓存的过程以下(来自网络):chrome

manifest

支持性

主流浏览器都支持manifest应用缓存技术. 以下表格:api

IE Edge Firefox Chrome Safari Opera ios Android
10+ 12+ 3.5+ 4+ 4+ 11.5+ 7.1+ 2.3+

H5标准中, Offline Web applications 部分有以下描述:浏览器

This feature is in the process of being removed from the Web platform. (This is a long process that takes many years.) Using any of the offline Web application features at this time is highly discouraged. Use service workers instead. [SW]

所以后续我将在其余文章中继续介绍 service workers, 本篇继续关注manifest.

如何开启应用缓存

manifest使用缓存清单进行管理, 缓存清单须要与html标签进行关联. 以下:

<html manifest="test.appcache">
  ...
</html>

在html标签中指定manifest文件, 便表示该网页使用manifest进行离线缓存. 该网页内须要缓存的文件列表须要在 test.appcache 文本文件中指定.

manifest缓存清单

就像写做文同样, manifest采用经典的三段式. 分别为: CACHE, NETWORKFALLBACK. 以下, 先看一个栗子?:

CACHE MANIFEST
# v1.0.0
content.css

NETWORK:
app.js

FALLBACK:
/other 404.html

其中第一行必须以 CACHE MANIFEST 开头, 后可跟若干字符注释, 注释从#号开始. 跟在 CACHE MANIFEST 行后的文件, 每行列出一个, 这些文件是须要缓存的文件. 所以 content.css 会被缓存, 不须要访问网络.

第二段内容以 NETWORK: 开始, 跟在该行后的文件表示须要访问网络. 如: app.js 将直接从网络上下载, 并不走manifest cache, 若是除了第一段中缓存的文件之外, 其余文件都从网络上获取, 那么此时可将 app.js 改成 * (通配符).

第三段内容以 FALLBACK: 开始, 跟在该行后的文件表示会有一个替代方案. 如: 当访问 /other 路径时, 若是访问失败, 那么将自动加载 404.html 做为替代.

manifest缓存状态

每一个manifest缓存都有一个状态, 标示着缓存的状况. 一份缓存清单只有一个缓存状态, 即便它被多个页面引用. 如下是各个缓存状态:

  • UNCACHED(未缓存): 代表应用缓存对象尚未初始化完成.

  • IDLE(空闲): 应用缓存并未处于更新状态.

  • CHECKING(检查): 正在检查是否存在更新.

  • DOWNLOADING(下载): 清单更新后, 从新下载所有资源到临时缓存中.

  • UPDATEREADY(更新就绪): 新版本的缓存下载完成, 所有就绪, 随即触发事件 updateready.

  • OBSOLETE(废弃): 应用缓存已被废弃.

上述缓存状态常量依次取值0, 1, 2, 3, 4, 5.

applicationCache

applicationCache是操做应用缓存的瑞士军刀, 也是惟一的一把刀.

首先咱们来获取该对象.

//webview下
var cache = window.applicationCache;
//shared worker中
var cache = self.applicationCache;

如下是其属性和方法介绍(大神请绕过):

  • status: 返回当前页面的应用缓存的状态, 一般开启应用缓存的页面可能返回1, 其余页面则返回0.

  • update(): 手动触发应用缓存的更新.

(1) 如有更新, 则依次触发①检查事件(Checking event), ②下载事件(Downloading event), ③下载进度事件(Progress event), ④更新完成事件(UpdateReady event);

(2) 若无更新, 则依次触发①检查事件(Checking event), ②无更新事件(NoUpdate event);

(3) 在未开启应用缓存的页面调用将抛出Uncaught DOMException 错误.

update() 方法一般在长时间不关闭的页面使用, 好比说邮箱应用, 用于按期检测可能的更新.

  • abort(): 取消应用缓存的更新. 可用于节省有限的网络带宽.

  • swapCache(): 若是存在一个更新版本的应用缓存, 那么它将切换过去, 不然将抛出 Uncaught DOMException 错误. 一般, 咱们会在updateready事件触发以后手动调用swapCache()方法, swapCache的切换只对后续加载的缓存文件有效, 已经加载成功的资源并不会从新加载.

那么如何利用好上述api更新一个页面的应用缓存呢? 别急, Beginner's Guide to Using the Application Cache 一文中提供了以下的样板方法:

// 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.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      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);

manifest缓存独立性

  1. manifest的缓存和浏览器默认的缓存是两套机制, 相互独立, 而且不受浏览器缓存大小限制(Chrome下测试结果).

  2. 各个manifest文件的缓存相互独立, 各自在独立的区域进行缓存. 即便是缓存同一个文件, 也可能因为缓存的版本不一致, 而形成各个页面资源不一致.

manifest缓存规则

  1. 遵循全量缓存的规律. 即: manifest文件改动后, 将从新缓存一遍全部的文件(包括html自己和动态添加的须要缓存的文件,即便缓存列表中没有该html). 第一次缓存过程当中若是出现缓存失败的文件, 那么, 第二访问, 又将从新缓存一遍全部的文件. 以此类推.

  2. manifest文件自己不能写进缓存清单, 不然连同html和资源在其缓存失效以前, 将永远不能得到更新.

  3. 即便manifest文件丢失, 缓存依然有效. 不过今后之后, 引入该manifest的html, 将永远不能得到更新.

webview的缓存现象

一般, webview的缓存有以下三种现象:

  1. 普通网页(无manifest文件), 不受manifest缓存影响, 缓存只走 http cache.

  2. 包含manifest文件的网页, 缓存文件只受manifest缓存影响(只有manifest文件改变时才会更新缓存资源), 缓存资源彻底与 http cache 无关, 可是 NETWORK 段落后须要访问网络的文件, 将继续走 http cache.

  3. webview直接加载manifest缓存过的文件时, 优先加载第一个manifest缓存的该文件, 若是没有找到manifest缓存, 那么它将自动寻找 http cache 或者 在线加载.

最佳实践

  1. 一般只使用一个manifest文件, 并保证缓存的文件尽量的少, 以减少manifest每次更新清单中文件所耗费的时间和流量.

  2. 若是必定要使用两个及以上manifest文件, 缓存文件请尽可能不要相同.

  3. 若是以上两条都不能保证, 那么, 请保证尽量在manifest缓存的状态更新时, 主动去刷新网页.(此时并不能保证不一样网页之间同一个缓存文件版本一致)

具体落地步骤

  1. 若是缓存的文件须要加参数运行, 建议将参数内容加到hash中, 如:cached-page.html#parameterName=value

  2. manifest 的引入可使用绝对路径或者相对路径, 若是你使用的是绝对路径, 那么你的manifest文件必须和你的站点处于同一个域名下.

  3. manifest文件你能够保存为任意的扩展名, 可是响应头中如下字段须取如下定值, 以保证manifest文件正确被解析, 而且它没有http缓存.

    Content-Type: text/cache-manifest
    Cache-Control: max-age=0
    Expires: [CURRENT TIME]

如何更新缓存

  1. 更新manifest文件后, webview将自动更新缓存.

  2. js更新缓存(手动触发manifest更新): window.applicationCache.update();

其余

chrome浏览器下经过访问 chrome://appcache-internals/ 能够查看缓存在本地的资源文件.

另外, 除了本文参考的一篇 MDN 的文章以及 HTML5 Rocks的 Beginner's Guide to Using the Application Cache 一文, 还有以下三个连接可供您比较阅读, 谢谢.


本问就讨论这么多内容,你们有什么问题或好的想法欢迎在下方参与留言和评论.

本文做者: louis

本文连接: http://louiszhai.github.io/20...

参考文章

相关文章
相关标签/搜索