Neekey

在此记录我的学习&生活.

Offline Web Applications -- Manifest小试

| Comments

manifest

今天简单地对HTML5的Offline特性进行了了解,把一些简单表层的知识点总结,分享下。


什么是Manifest

为了让用户在没有网络连接的状况下能继续的使用Web Application,HTML5提供了对于Offline的支持:通过一个叫做manifest的配置文件,我们可以提供一个列表,让浏览器缓存我们指定的文件,并在以后的请求中都直接直接使用本地的缓存文件而不用去向服务器请求数据。

HTML5便是通过这种机制来实现离线应用

注意:manifest的缓存控制是覆盖Http的那些缓存机制的(cache-control/304)

配置manifest

  • 在我们的html标签中引入manifest文件

<html manifest="mysite.manifest">

  • manifest文件的Content-Type值必须为text/cache-manifest

然后我们就可以通过编辑manifest文件来对缓存做配置了。

manifest语法

先看一个例子w3.org上提供的例子吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- clock.html -->
<!DOCTYPE HTML>
<html manifest="clock.appcache">
 <head>
  <title>Clock</title>
  <script src="clock.js"></script>
  <link rel="stylesheet" href="clock.css">
 </head>
 <body>
  <p>The time is: <output id="clock"></output></p>
 </body>
</html>
/* clock.css */
output { font: 2em sans-serif; }
/* clock.js */
setTimeout(function () {
    document.getElementById('clock').value = new Date();
}, 1000);

其中的manifest文件clock.appcache内容如下:

1
2
3
4
ACHE MANIFEST
clock.html
clock.css
clock.js

运行这个例子,除了第一次是正常的200请求外,此后观察网络,你会发现,不管你怎么强刷页面,都是直接from cache

manifest-example

下面我们简单介绍一下manifest的语法

  • 必须以CACHE MANIFEST作为第一行出现,任何不符合这条规则的manifest都会被浏览器忽略
  • 使用 # 作为注释,比如
1
2
# 我是注释君
  # 我是前面有空格的注释君

不过一行中只能有注释,注释和内容不能在同一行中。

  • CACHE: 作为标示符,用来表示该行下方的内容都是需要缓存的文件

下面的文件列表,每一行一个文件,文件可以是相对路径(相对该manifest文件),也可以是绝对路径,如:

1
2
3
CACHE:
index.css
http://demos/index/assets/js/index.js
  • NETWORK: 作为标示符,用来表明该行下面的内容都不走缓存,都请求网络

CACHE的写法一样,不过NETWORK支持通配符*,但是不支持包含路径的同配…

1
2
3
4
5
NETWORK:
#将匹配所有的资源
*
#下面的无效
assets/*
  • FALLBACK: 作为标示符,用来表明该行下面的内容都是fallback的内容

该列表用来指定,如果一个资源请求失败,则请求另一个资源,如:

1
2
FALLBACK:
noexists.css clock.css

这个功能非常神奇,至少从网络这块来看似乎是无缝的,看chrome控制台截图:

manifest

如何更新缓存?

缓存到本地,速度是快了,没网也能用,那要更新文件怎么办?

更新manifest文件!

每次浏览器都会去先去检查manifest是否有更新,如果有更新,就会重新请求列表中的所有CACHE文件,并替换掉本地的缓存。

注意,在修改了manifest之后,页面第一次访问的时候,虽然浏览器会重新请求CACHE列表中的文件,但是页面上使用的脚本和样式以及图片等将还是原有的,到第二次访问的时候才会是新的。

为什么呢?我的理解是,页面上的资源请求和manifest的请求是并发的,因此第一次访问,页面上的资源(那些被缓存的)还是会按照原来去读本地的缓存,而此时新版本的资源还没到位,还来不及替换浏览器中保留的旧版本的资源。

浏览器处理manifest的过程

下面内容直接翻译自官方Event Summary,markdown不支持表格,排版上有点蛋疼,大家将就着看吧:

  • checking: 浏览器检查manifest是否有更新,或者是第一次请求。
  • noupdate: 如果manifest没有改变,则结束
  • downloading: 浏览器发现了manifest的改变后者在下载manifest中罗列的资源
  • progress: 浏览器在下载manifest中罗列的资源
  • cached: manifest中罗列的资源已经下载完毕,并被缓存完毕
  • updateready: manifest中罗列的资源均为重新下载,此时可以使用JavaScript使用window.applicationCache.swapCache()将缓存切换到最新的状态,整个过程结束
  • obsolete: manifest请求返回了404或者410,则本地缓存将被删除,整个过程结束
  • error: 好吧… 反正就是出错了,整个过程结束

浏览器兼容器

Chrome / Safari / Firefox / Opera

IE9表示不支持

存在的一些问题和注意点

页面文件本身会被缓存!

是的,不只是是默认,是会一直被缓存,即使你把页面文件放到NETWORK下面去,还是会被缓存… 悲剧,这个需要再研究下,有没有好的解决方案。

将文件从CACHE中删除出错

文件从CACHE中删除出错后,你会发现浏览器无论如何都请求不到这些资源了… 直接显示的是fail… 解决方案是将这些文件添加到NETWORK列表中

跨域

这个地方没细究,不过在FALLBACK中,替代方案的连接如果被替换的资源不在同一个域中,就会失败…

小小地总结一下

总体上来说,manifest是个好东西,想想一下全站资源都被缓存到,对与性能的提升就知道了,但是如上面所述如果要应用到实际环境中,还是有很多问题,另外还有很多细节也还需要调研清楚。

总体来说,觉得这个东西安装上去后不好卸下,请慎用。

这篇文章毕竟是小试,其实关于manifest还有很多细节(比如manifest中罗列出资源会不会影响第一次的资源请求顺序)需要验证和研究,以后的文章中继续补充

Comments