AppCache?
三个优势
- 离线浏览——用户在不能联网的时候依然能浏览整个站点
- 高速——缓存资源是存储在本地的,因此能更快加载。
- 更小的服务器负载——浏览器只需要从服务器端下载有改变的资源即可,相同资源不需要重复下载。
Application Cache(或 AppCache)让一个开发者可以指定浏览器需要保存哪个文件。当用户在离线情况下时,即使他们按了刷新按钮,你的应用也能正确加载和工作。
离线本地存储和传统的浏览器缓存有什么不同?离线存储为整个web提供服务,浏览器缓存只缓存单个页面;
离线存储可以指定需要缓存的文件和哪些文件只能在线浏览,浏览器缓存无法指定;
离线存储可以动态通知用户进行更新。
实现机制
1,appcache文件格式
cache manifest文件是一个简单的文本文件,其中列出了浏览器需要缓存的资源。
- CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存,等价于CACHE:
- NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
- FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)可选部分,指定了如果资源获取失败,将会呈现怎样的页面。第一个URL是资源,第二个就是fallback页面。两个URL都必须是相对地址,并且由同一个manifest文件指定。可以使用Wildcards
一个简单的manifest文件看起来可能是下面这样的:
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
下面来看一个更复杂的例子:
CACHE MANIFEST
# 2010-06-18:v2
# Explicitly cached ‘master entries’.
CACHE:
/favicon.ico
index.html
stylesheet.css
images/logo.png
scripts/main.js
# Resources that require the user to be online.
NETWORK:
login.php
/myapi
http://api.twitter.com
# static.html will be served if main.py is inaccessible
# offline.jpg will be served in place of all images in images/large/
# offline.html will be served in place of all other .html files
FALLBACK:
/main.py /static.html
images/large/ images/offline.jpg
*.html /offline.html
以“#”开头的都是注释,这些注释还可以起到另外的作用。一个应用只有在manifest文件发生变化时才会更新 cache。例如,如果你编辑了图像或是改写了一个Javascript函数,cache并不会发生更新。你必须改写manifest文件本身来通知浏览 器需要更新cache文件了。通过在manifest文件中添加一行注释,在其中写上版本号,或者文件hash值,或者时间戳,你都可以确保用户拥有你的 软件的最新版本。如果有新版本出现,你同样可以以编程的方式更新cache,就跟在Updating the cache 中所讨论的那样。
2,引用一个MANIFEST文件
为了让一个应用能启用application cache,需要在文档的html标签中包含manifest属性,如下所示:
你需要在你想要缓存的web app的每一页中都包含 manifest 属性。如果一个页面没有 manifest属性,它不会被缓存(除非在manifest文件中显式指定了这 个页面)。这意味着只要用户访问的页面包含manifest属性,它都将会被加入application cache中。这样,就不用在manifest文件中指定需要缓存哪些页面了。
Manifest属性可以指定一个绝对URL或是一个相对路径,但是,一个绝对URL需要和web app是同源的。一个manifest文件可以是任何扩展文件类型,但必须有正确的mime-type。如下所示:
1
2
3
4
5
|
<
html
manifest=”http://www.example.com/example.mf”>
…
|
注意:引用了你的manifest文件的HTML文件都会自动被缓存,因此,没有必要在你的manifest文件中再指定这个文件,但是,在manifest文件中指定这个文件是一种更好的做法。
注意:页面上基于SSL的HTTP cache headers以及caching restrictions都会被cache manifests重写。因此,基于https的页面也能离线工作。
注意: 主页一定会被缓存起来的,因为AppCache主要是用来做离线应用的,如果主页不缓存就无法离线插件了,因此把index.html添加到NETWORK中是不起效果的。
cache更新
window.applicationCache 对象是对浏览器的应用缓存的编程访问方式。其 status 属性可用于查看缓存的当前状态:
为了通过编程更新cache,首先调用 applicationCache.update()。这将会试图更新用户的 cache(要求manifest文件已经改变)。最后,当 applicationCache.status 处于 UPDATEREADY 状态时, 调用applicationCache.swapCache(),旧的cache就会被置换成新的。
- var appCache = window.applicationCache;
- appCache.update(); // Attempt to update the user's cache.
- ...
- if (appCache.status == window.applicationCache.UPDATEREADY) {
- appCache.swapCache(); // The fetch was successful, swap in the new cache.
- }
注意:像这样使用 update()和swapCache()并不会将更新后的资源 呈现给用户。这仅仅是让浏览器检查manifest文件是否发生了更新,然后下载指定的更新内容,重新填充app cache。因此,要让用户看到更新后的内容,需要两次页面下载,一次是更新app cache,一次是更新页面内容。
好消息是,你可以避免两次页面下载带来的麻烦。为了让用户能看到你的站点的最新版本,设置一个监听器来监听页面加载时的updateready 事件。
- //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);
一个简单的离线缓存的应用
未添加AppCache情况
再次刷新页面也会更新这些文件(当文件内容并无实际更新是也会发起http请求, http返回304, 但也会发起http请求)
添加AppCache
添加文件index.appcache, 内容为:
同时修改index.html, 添加
再次请求index.html,
结果如下,第一次请求会把所有文件都拉下来,这里就不列出了, 同时会请求index.appcache文件.
刷新页面会发现只请求了一个文件:
这时修改index.html文件再次请求并不会更新index.html文件, 说明index.html已经缓存,并不会从server端获取。