资讯专栏INFORMATION COLUMN

聊一聊H5应用缓存-Manifest

陈伟 / 1513人阅读

摘要:原文聊一聊应用缓存导读是提供的一种应用缓存机制基于它应用可以实现离线访问为此浏览器还提供了应用缓存的虽然的技术已被标准废弃但这不影响我们尝试去了解它也正是因为的应用缓存机制如此诱人饿了么和邮箱等都还在使用着它描述对熟悉的同学可以跳过此

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

导读

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

描述

对manifest熟悉的同学可以跳过此节.

鉴于manifest应用缓存的技术, 我们可以做到:

离线访问: 即使服务器挂了, 或者没有网络, 用户依然可以正常浏览网页内容.

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

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

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

支持性

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

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文件, 便表示该网页使用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缓存独立性

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

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

manifest缓存规则

遵循全量缓存的规律. 即: manifest文件改动后, 将重新缓存一遍所有的文件(包括html本身和动态添加的需要缓存的文件,即使缓存列表中没有该html). 第一次缓存过程中如果出现缓存失败的文件, 那么, 第二访问, 又将重新缓存一遍所有的文件. 以此类推.

manifest文件本身不能写进缓存清单, 否则连同html和资源在其缓存失效之前, 将永远不能获得更新.

即使manifest文件丢失, 缓存依然有效. 不过从此以后, 引入该manifest的html, 将永远不能获得更新.

webview的缓存现象

通常, webview的缓存有如下三种现象:

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

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

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

最佳实践

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

如果一定要使用两个及以上manifest文件, 缓存文件请尽量不要相同.

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

具体落地步骤

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

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

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

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

如何更新缓存

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

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

其他

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

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

Cache manifest in HTML5 on Wikipedia

Offline Web Applications W3C Working Group Note

Offline Web applications at WHATWG


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

本文作者: louis

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

参考文章

Using the application cache | MDN

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/61854.html

相关文章

  • [一聊系列]一聊百度移动端首页前端速度那些事儿

    摘要:要快,但是我们的服务也必须万无一失,后续我会分享百度移动端首页的前端架构设计那么这样的优化,是如何做到的呢,又如何兼顾稳定性,架构性,与速度呢别急,让我们把这些优化一一道来。百度移动端首页的很多就是这样缓存在客户端的。 欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码):https://segmentfault.com/blog/fronte...

    The question 评论0 收藏0
  • webpack的编译&构建

    摘要:的编译构建上一篇文章详解中介绍了基于事件流编程,是个高度的插件集合,整体介绍了的编译流程。本文将单独聊一聊最核心的部分,编译构建。的编译重要的构建节点的构建中总会经历如下几个事件节点。 webpack的编译&构建 上一篇文章webpack详解中介绍了webpack基于事件流编程,是个高度的插件集合,整体介绍了webpack 的编译流程。本文将单独聊一聊最核心的部分,编译&构建。 web...

    roland_reed 评论0 收藏0
  • 一聊事件委托

    摘要:今天想使用点击事件绑定动态获取的元素,但又不想将事件注册在成功函数体内。 今天想使用点击事件绑定动态获取的元素,但又不想将事件注册在post成功函数体内。 事件委托,顾名思义就是讲子元素事件委托给上级元素 (这是写上级元素,包含document根元素,因为不局限于它的父元素) 先说一下为什么动态获取的元素直接绑定不可以: 因为动态元素是后生成的,在事件注册的时候,它还没有生成,一般...

    URLOS 评论0 收藏0
  • [一聊系列]一聊前端存储那些事儿

    摘要:如图图顾名思义,,是级别的存储。如笔者写的一篇浅析文章聊一聊百度移动端首页前端速度那些事儿读者们可以尝试使用。 欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码):https://segmentfault.com/blog/frontenddriver 在web开发越来越复杂的今天,前端拥有的能力也越来越多。其中最重要的一项莫过于web存储。...

    caige 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<