一、介绍
最简单来说,一个离线网络应用程序就是一个URL的列表——HTML,CSS,JavaScript,图片,或者其他类型的资源。离线网络应用程序的主要指向一个叫做名单文件并用于定位网络服务器上的资源列表。用于执行HTML5离线以用程序的网络浏览器将从名单文件中读取URL列表,下载这些资源,将他们在本地缓存,并自动在这些本地副本改变时保持他们更新。当你尝试在没有网络连接时访问网络应用程序,你的网络浏览器将自动切换并使用本地代替。
最新的主流的浏览器中都已添加了对HTML5的offlineStorage功能的支持,HTML5离线存储功能非常强大,它的作用是:在用户没有与因特网连接时,照样可以访问站点或应用,在用户与因特网连接时,自动更新缓存数据,是我们的网站的适应性和应用型更强!
例如一些在线游戏的某些文件可以使用离线存储缓存到本地,这样就不用每次刷新页面都要下载了。对于传统的浏览器缓存是无法控制的,浏览器有自己的缓存规则,我们无法实现缓存什么不缓存什么。但是使用离线存储可以缓存任何内容,包括可以自定义哪些可以被缓存,哪些必须联网才能访问。
离线存储所保存的不是应用中的某些数据,而是站点的某个些文件的副本,即html页面或图片等,而不是仅仅存储一段json或xml。
二、浏览器支持情况
Firefox Safari Chrome iPhone Android 基本都支持了,但有些低版本还不支持。但是支持的都不是很好,并且使用方式也有所不同,甚至有些API都无法实现。
三、开始使用
1.配置web服务器支持manifest解析
离线存储需要使用一个manifest文件来在服务端指定客户端的缓存规则,所以需要web服务器的支持,需要在服务器上配置以实现让服务器可以解析manifest文件。
Apache的配置,在httpd.conf中增加以下配置:
如果使用的是Tomcat,配置如下:
tomcat的配置,在$TOMCAT_HOME$/conf/web.xml中增加以下配置:
<mime-mapping>
<extension>manifest</extension> <!--离线配置文件后缀名-->
<mime-type>text/cache-manifest</mime-type>
</mime-mapping>
这个配置可以放在<web-app>内的任意位置,但是最好和已有的<mime-mapping>配置在一起。
2.编写html、css、js等页面元素,与之前没有区别
3.编写manifest文件
例如:
CACHE MANIFEST #上面这一句前后不能能有空格,且要作为文件的第一行,所以上面不能有备注 #这一句指明要缓存的内容,每个文件占用一行,被缓存文件需要指定相对于该文件的路径 CACHE: offlinestorage.html #以为html和这个manifest在同一个文件夹下,所以不用指定相当于manifest的路径 style/style.css js/script.js
#声明用于指定无需缓存的文件,也就是必须联网才能访问的内容 NETWORK: image/104.jpg
#这个声明允 许你在资源不可用的情况下,将用户重定向到特定文件,也就是配置替代方案 #例如 style.css不可访问时就将style2.css缓存,指定的代替文件也必须存在才可以,否则解析出错 FALLBACK: |
4.在html主页面中引入manifest
<!-- 将manifest文件与html文件关联,且路径要能从html找到manifest文件 这样当访问这个html文件时浏览器才会识别出manifest中要缓存的内容,然后去下载 --> <html lang="zh-CN" manifest="mycache.manifest"> |
然后在浏览器访问这个页面的时候就会将manifest中指定的资源缓存到浏览器本地,然后停止web服务器之后对于已经缓存的内容仍然可以使用原来的url正常访问。这就是HTML5离线存储的最基本内容。
四、存在的问题及解决
如果现在被缓存的内容在服务端做了更改,例如html页面中增加了一些内容,此时因为这个html已经缓存到了本地,所以此时再访问这个url是无法读取到服务器更新后的html的。因为只要本地有,并且manifest没有改变,那么就会一直读取本地的而不会读取服务器上最新的。所以服务器上更新的html,即最新版本的资源就无法被访问到了,这是一个比较严重的问题。
因为是manifest没有改变才会导致一直读取本地缓存的资源,所以为了解决这个问题,可以讲manifest做一下修改,例如增加或减少一点注释信息,只要做任何修改即可,那么服务器就会重新加载这个manifest,浏览器也会根据manifest的配置重新读取资源并缓存。这样就可以实现读取最新的资源了。并且需要刷新两次才能显示出新的内容,第一次刷新会读取manifest的资源并重新缓存,第二次才会读取新缓存并显示。
总之就是,浏览器发现manifest文件本身发生变化,便会根据新的manifest文件去获取新的资源进行缓存。当manifest文件列表并没有变化的时候,我们通常通过修改manifest注释的方式来改变文件,从而实现更新。
但是这种每次资源内容变化就手动更新manifest文件的方式显然在实际应用中是不可取的,因为html页面的内容通常都是动态变化的,所以无法做到每次变化都更新manifest文件。
五、在线状态检测
可以通过JavaScript的方式来操作manifest文件以达到及时的更新,但是目前还达不到实际的要求。因为JavaScript对于HTML5的离线存储的一些方法、属性、事件在不同浏览器中实现方式有差别,且实现的也不是很好,例如同一个属性在不同浏览器中得到的值也不同。所以后面内容作为了解即可,例如applicationCache的属性、事件、方法。
HTML5提供了两种检测是否在线的方式:navigator.onLine属性和online/offline事件用于判断资源是否在线,即是否可以通过web服务器访问到资源。但是onLine只是检测是否连接,而不是像ping那样检测路由,也就是当前机器连接到局域网可能是onLine是返回true,但实际并不能上网,因为此时没有广域网。
1.navigator.onLine属性表示当前是否在线。如果为true,表示在线;如果为false,表示离线。
2.开发者还需要在网络状态发生变化时立刻得到通知,因此HTML5 还提供了online/offline 事件用于判断资源是否在线或离线,即是否可以通过web服务器访问到最新的资源。
六、applicationCache属性API
applicationCache是window对象下的一个子对象,例如window.applicationCache。其中该对象的属性status返回缓存的状态,取值和含义如下:(下面appCache应当是applicationCache)。也即是在某个html页面中白那些js脚本,通过该对象判断该页面是否是已经被离线存储到本地等信息。一般在window.onload函数中访问该对象以判断该页面是否可以被离线访问。
七、applicationCache事件API
applicationCache缓存事件API的接口以及事件的含义如下:
例如:指定progress事件,只要任何一个离线文件被下载成功,就会执行该事件处理函数。
window.onload=function(){
window.applicationCache.addEventListener(“progress”, function(e){
alert(“new file downloaded!”);
},false);
};
八、applicationCache方法API
例如update()方法,如果缓存的资源在服务器行有变化,则会自动下载最新的缓存。swapcache()方法会在刷新的时候自动判断资源是否过期,即之前更新了manifest文件之后也需要刷新两次才能得到最新的资源,如果使用swapcache()则只需要刷新一次即可,会自动判断本地所缓存的资源是否是最新的。
例如:手动添加更新的事件
window.applicationCache.addEventListener(“upadteready”,function(e){
window.applicationCache.swapCache();
alert(“Cache updated!”);
},false);
对于updateready事件,即使manifest文件中指定文件已经下载成功,但用户不一定能看到最新下载的文件,所以需要使用swapCache()将最新下载到的文件更新到应用中,以实现及时展现给用户。
也可以使用setInterval()定期唤醒更新事件,不断的处理updateready事件和调用swapCache()。还可以使用HTML5最新提供的webworkers来实现异步的操作以代替setInterval的方式。
九、使用离线存储的注意事项
1. 站点离线存储的容量限制是5M
2.如果manifest文件,或者内部列举的某一个文件不能正常下载,整个更新过程将视为失败,浏览器继续全部使用老的缓存
3.引用manifest的html必须与manifest文件同源,在同一个域下
4.在manifest中使用的相对路径,相对参照物为manifest文件
5.CACHE MANIFEST字符串应在第一行,且必不可少
6.系统会自动缓存引用清单文件的HTML 文件
7.manifest文件中CACHE则与NETWORK,FALLBACK的位置顺序没有关系,如果是隐式声明需要在最前面
8.FALLBACK中的资源必须和manifest文件同源
9.当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
10.站点中的其他页面即使没有设置manifest属性,请求的资源如果在缓存中也从缓存中访问
11.当manifest文件发生改变时,资源请求本身也会触发更新
对于是否能获取离线数据,还和浏览器的设置有关,例如设置了每次都不读取缓存,那么离线存储就失效了,需要开启浏览器的可读取缓存才可以。
注:部分内容摘自后盾网HTML5教程的PPT