离线Web应用程序介绍
在HTML5中新增了一个API,为离线Web应用程序的开发提供了可能性。为了让Web应用程序在离线状态时也能正常工作,就必须要把所有构成Web应用程序的资源文件,诸如:HTML文件、CSS文件、JavaScript脚本文件等放在本地缓存中,当服务器没有和Internet建立连接的时候,也可以利用本地缓存中的资源文件来正常运行Web应用程序。
本地缓存与浏览器网页缓存的区别
首先,本地缓存是为整个Web应用程序服务的,而浏览器的网页缓存只服务于单个网页,任何网页都具有网页缓存,而本地缓存只缓存那些指定缓存的网页。
其次,网页缓存也是不安全、不可靠的,因为我们不知道在网站中到底缓存了哪些页面,以及缓存了网页上的哪些资源。而本地缓存是可靠的,我们可以控制对哪些内容进行缓存,不对哪些内容进行缓存,开发人员还可以用编程的手段来控制缓存的更新,利用缓存对象的各种属性、状态和事件来开发出更为强大的离线应用程序。
manifest文件
Web应用程序的本地缓存是通过每个页面的manifest文件来管理的。manifest文件是一个简单文本文件,在该文件中以清单的形式列举了需要被缓存或不需要被缓存的资源文件的文件名称、以及这些资源文件的访问路径。可以为每一个页面单独指定一个mainifest文件,也可以对整个Web应用程序指定一个总的manifest文件。manifest文件示例如下:
CACHE MANIFEST #文件的开头必须书CACHE MANIFEST #该manifest文件的版本号 #version 7 CACHE: other.html hello.js images/myphoto.jpg NETWORK: http://google.com/xxx NotOffline.jsp * FALLBACK: online.js locale.js CACHE: newhello.html newhello.js
在manifest文件中,第一行必须是“CACHE MANIFEST”文字,以把本文件的作用告知给浏览器,即对本地缓存中的资源文件进行具体设置。同时,真正运行或测试离线Web应用程序的时候,需要对服务器进行配置,让服务器支持text/cache-manifest这个MIME类型(在HTML5中规定manifest文件的MIME类型为text/cache-manifest) 。
在manifest文件中,可以加上注释来进行一些必要的说明或解释,注释行以“#”开始;文件中可以(而且最好)加上版本号,以表示该manifest文件的版本,版本号可以是任何形式的,更新文件时一般也会对该版本号进行更新。
指定资源文件,文件路径可以是相对路径,也可以是绝对路径。指定时每个资源文件为一行。在指定资源文件的时候,可以把资源文件分为三类,分别是“CACHE”、“NETWORK”和“FALLBACK”。
- 在CACHE类别中指定需要被缓存在本地的资源文件。为某个页面指定需要本地缓存的资源文件时,不需要把这个页面本身指定在CACHE类型中,因为如果一个页面具有manifest文件,浏览器会自动对这个页面进行本地缓存。
- NETWORK类别为显式指定不进行本地缓存的资源文件,这些资源文件只有当客户端与服务器端建立连接的时候才能访问。该示例中的“*”为通配符,表示没有在本manifest文件中指定的资源文件都不进行本地缓存。
- FALLBACK类别中指定两个资源文件,每一个资源文件为能够在线访问时使用的资源文件,第二个资源文件为不能在线访问时使用的备用资源文件。
每个类别都是可选的。但是如果文件开头没有指定类别而直接书写资源文件的时候,浏览器把这些资源文件视为CACHE类别,直到看见文件中第一个被书写出来的类别为止,并且允许在同一个manifest文件中重复书写同一类别。
为了让浏览器能够正常阅读该文本文件,需要在Web应用程序页面上的html元素的manifest属性中指定manifest文件的URL地址。指定方法如下:
<!-- 可以为每个页面单独指定一个manifest文件 --> <html manifest="hello.manifest"> </html> <!-- 也可以为整个Web应用程序指定一个总的manifest文件 --> <html manifest="global.manifest"> </html>
通过这些步骤,将资源文件保存到本地缓存区的基本操作就完成了。当要对本地缓存区的内容进行修改时,只要修改manifest文件就可以了。文件被修改后,浏览器可以自动检查manifest文件,并自动更新本地缓存区中的内容。
浏览器与服务器的交互过程
首次访问网站时的交互过程如下:
- 浏览器请求访问网站;
- 服务器返回请求网页,例如:index.html;
- 浏览器解析网页,请求页面上所有资源文件,包括HTML文件、图像文件、CSS文件、JS文件以及manifest文件;
- 服务器返回所有资源文件;
- 浏览器处理manifest文件,请求manifest中所有要求本地缓存的文件,包括index.html页面本身,即使刚才已经请求过这些文件。如果你要求本地缓存所有文件,这将是一个比较大的重复的请求过程;
- 服务器返回所有要求本地缓存的文件;
- 浏览器对本地缓存进行更新,存入包括页面本身在内的所有要求本地缓存的资源文件,并且触发一个事件,通知本地缓存被更新。
现在浏览器已经把本地缓存更新完毕,如果再次打开浏览器访问该网站,而且manifest文件没有被修改过,它们的交互过程如下:
- 浏览器再次请求访问网站;
- 浏览器发现这个页面被本地缓存,于是使用本地缓存中index.html页面;
- 浏览器解析index.html页面,使用所有本地缓存中的资源文件;
- 浏览器向服务器请求manifest文件;
- 服务器返回一个304代码,通知浏览器manifest没有发生变化。
只要页面上的资源文件被本地缓存过,下次浏览器打开这个页面时,总是先使用本地缓存中的资源,然后请求manifest文件。
如果再次打开浏览器时,manifest文件已经被更新过了,那么浏览器与服务器之间的交互过程如下:
- 浏览器再次请求访问网站;
- 浏览器发现这个页面被本地缓存,于是使用本地缓存中的index.html页面;
- 浏览器解析index.html页面,使用所有本地缓存中的资源文件;
- 浏览器向服务器请求manifest文件;
- 服务器返回更新过年manifest文件;
- 浏览器处理manifest文件,发现该文件已被更新,于是请求所有要求进行本地缓存的资源文件,包括index.html页面本身;
- 服务器返回要求进行本地缓存的资源文件;
- 浏览器对本地缓存进行更新,丰入所有新的资源文件。并且触发一个事件,通知本地缓存被更新。
需要注意的是,即使资源文件被修改过了,在上面的第三步中已经装入的资源文件是不会发生变化的,例如图片不会突然变成新的图片,脚本文件也不会突然使用新的脚本文件,也就是说,这时更新过后的本地缓存中的内容还不能被使用,只有重新打开这个页面的时候才会使用更新过后的资源文件。另外,如果不想修改manifest文件中对于资源文件的设置,但是对服务器上请求缓存的资源文件进行了修改,那么可以通过修改版本号的方式来让浏览器认为manifest文件已经被更新过了,以便重新下载修改过的资源文件。