离线缓存

本文也同步发表在我的公众号“我的天空

 

 

 

HTML5支持离线缓存功能,该功能能够在第一次浏览页面后将相关资源与文件在本地缓存起来,这样在下次访问时,这些资源就不需要再从服务器上下载,同时如果是在断网的情况下,也能够正常显示。该功能虽好,但是在学习的过程中还是要注意一些思维误区,避免掉入坑中,我们先来学习一下如何使用离线缓存功能。

 

如何使用离线缓存


离线缓存功能的启用还是比较简单的,在w3c、以及其他的一些网上学习资料中,均有详细的说明,基本上是以下步骤:

 

1、在需要启用离线缓存功能的页面上在<htnl>标签中插入对于manifest文件的引用,如以下示例:

 

<html  manifest="test.manifest">

 

2、编辑manifest文件,如以上示例中对应的manifest的文件名即为test.manifest。manifest文件以“CACHE MANIFEST”开头,接下来分为“CACHE:”、“NETWORK:”、“FALLBACK:”三部分,当然这些不是必须的,且“CACHE:”关键字可以被省略。这三部分分别指定需要本地缓存的资源、不需要本地缓存的资源、以及出错后需访问的资源。如以下示例:

 

CACHE MANIFEST
# v1.01
CACHE:
a.js

 

NETWORK:
b.js

 

FALLBACK:
404.html

 

以上mainfest文件中,我们指定了需要本地缓存的是a,js,不要缓存的是b.js,如果出错了,则显示404.html。另外我们指定了一个版本信息“#v1.01”,这个不是mainfest文件规定的,但实际上会起到很重要的作用,我们在后面会说明。

 

接下来我们举个例子来演示一下本地缓存的使用,需要注意的时必须得部署为web服务才能体现效果。首先是index1.html文件,其引用了两个外部文件:a.js与b.js。

 

<!DOCTYPE HTML>
<html  manifest="test.manifest">
   <head>
     <title>index1</title>
     <script src="a.js"></script>
     <script src="b.js"></script>
 </head>

   <body>
      <p1>测试页面</p1>
   </body>
</html>

 

接下来是相应的test.manifest文件:

 

CACHE MANIFEST
# v1.01
a.js

NETWORK:
b.js

 

在index1.html中,我们指定了test.manifest文件,随后引入了a.js和b.js文件。在test.manifest文件中,我们指定了需要本地缓存的文件是a.js,不需要缓存的是b.js,要注意的是我们省略了“CACHE:”这一行关键字。

 

接下来我们在firefox里来看一下效果,首先将其部署在web服务中,老潘我用的是IIS,第一次访问index1.html页面时,我们在firefox中跟踪一下a.js与b.js的下载效果,发现a.js与b.js均正常下载:

 

 

接下来我们再次刷新页面,我们发现a.js已经是离线缓存的状态了(AppCache),而b.js仍然正常下载:

 

 

 

接下来我们把Web服务关闭,模拟断网的情况,我们发现a.js仍能正常访问,但是b.js已经无法访问了:

 

 

 

下面我们要面对的问题是如何更新已被缓存的资源?


更新已被缓存的资源

 

在实际应用中,我们必然会碰到资源更改的情况,而一旦资源被离线缓存,那么将永远不会去服务器上访问该资源。如以上例子中,如果我们的a.js修改了,那么如何去更新客户侧已被本地缓存的a.js呢?

 

答案是更新manifest文件,该文件更新后,则将重新下载之前已被离线缓存的资源,这样就达到了更新资源的目的。在之前的manfest文件示例中,我们增加了一个貌似多余的版本信息“#v1.01”,而当要更新manifest文件时,我们只需要修改一下这行,这样既记录了版本信息,又实现了文件的更新,这也是大家通用的方式。

 

另外要注意的是,更改了mainfest后,第一次刷新时是不会显示出文件更新效果的,需要第二次刷新才能生效。从这点也可以分析出离线缓存的运行机制:当页面加载时,首先获取mainfest文件,将里面记录的需离线缓存的文件从本地缓存中取出,渲染页面,同时会对mainfest版本进行对比,如果发现manifest文件发生了变更,则会重新从服务器上下载那些需离线缓存的文件,但是之前已经渲染好的页面不会再做更新。直到下一次访问时,才会使用那些已更新的离线缓存文件,才能看出更改的效果。

 

接下来讨论一个比较有趣的问题,也是离线缓存中很容易踏入的坑(其实我自己就掉坑里了),我们之前离线缓存的都是js、css之类的资源文件,那么加载它们的页面文件(如html)是怎么处理的?


页面文件的离线缓存问题

 

在刚接触离线缓存的时候,我们很自然的会想到,页面文件也应该被离线缓存,且离线缓存与更改机制跟资源文件一样,假设我们有两个文件index1.html与index2.html文件,我们想象index1被离线缓存,而index2不离线缓存,则我们很自然的会这样做:首先在index1和index2里都添加manifest="test.manifest",随后编写test.manifest文件:

 

CACHE MANIFEST
# v1.01
index1.html

NETWORK:
index2.html

 


我们期望在NETWORK中指定了index2.html,而使得index2.html不被离线缓存,但是很不幸,我们会沮丧的发现index2.html仍然被缓存了。

 

对于页面文件来说,只要指定了manifest文件,它就必然会被离线缓存,此时在NETWORK中指定是无效的,甚至不再manifest文件中指定也可以,其实在实际应用中,我们在manifest文件里设置的总是一些资源文件,如js、css、图片文件等,而不会去指定页面文件。 因此对于这些指定了manifest文件的页面文件,由于其实际上也在本地离线缓存了,因此对其更新也需要遵循之前资源文件更新的原则,即除了页面文件进行修改外,同时还得更新manifest文件,并且是第二次刷新才能看出修改的效果。

 

posted @ 2017-04-10 17:08  我的天空-老潘  阅读(598)  评论(0编辑  收藏  举报