应用程序存储和Web应用
应用程序缓存,允许Web应用将应用程序文件本地保存到用户的浏览器中。不像localStorage和sessionStorage只是保存Web程序相关的数据,它是将应用程序自身保存起来——应用程序的所有文件(HTML、CSS、JS、图片等)。
应用程序缓存和一般的浏览器缓存不同,它不会随着用户清除浏览器缓存而被清除。同时,缓存起来的应用程序也不会像一般固定大小的缓存那样,老数据会被最近一次访问的新数据代替掉。它其实不是临时存储在缓存中:应用程序更像是被安装在那里,除非被用户“卸载”或者“删除”,否则它就会一直存在。所以,总的来说,应用程序缓存在真正意义上不是缓存,应该称之为“应用程序存储”。
Web应用能够实现“本地安装”的目的是要保证它能够在离线状态(如在飞机上或者手机没信号的时候)下依然可访问。将自己“安装”到应用程序缓存中的Web应用,在离线状态下使用localStorage来保存应用相关的数据,同时还具备一套同步机制,在再次回到在线状态的时候,能够将存储的数据传输给服务器。
应用程序缓存清单
应用程序缓存清单:包含所有应用程序所依赖的所有URL列表。
可以在应用程序主HTML页面的标签中设置manifest属性,值指向该清单文件。
清单文件写法
1 2 3 4 5 |
<!DOCTYPE HTML> <html manifest="xuanfengge.appcache"> <head>...</head> <body>...</body> </html> |
清单文件中的首行内容必须以“CACHE MANIFEST”字符串开始。然后编写要缓存的文件URL列表,一行一个URL。相对路径的URL都相对于清单文件的URL,注释以#开头。
1 2 3 4 5 6 7 8 |
CACHE MANIFEST # 上一行标识此文件是一个清单文件,本行是注释 # 下面的内容都睡应用程序依赖的资源文件的URL index.html style.css init.js images/logo.png |
清单文件包含要缓存的应用的标识。如果一个Web应用有许多Web页面,那么每个HTML页面就需要设置属性来指向清单文件。
缓存清单的MIME类型
应用程序缓存清单文件以.appchche作为文件扩展名,但是Web服务器是通过”text/cache-manifest”这个MIME类型识别清单文件的。如果服务器讲清单文件的Content-Type的头信息设置成其他MIME类型,那么就不会缓存应用程序了。因此,可能需要对Web服务器做一定的配置来使用这个MIME类型。比如,在Web应用目录下创建Apache服务器的一个.htaccess文件。
复杂的清单
一个应用从应用程序缓存中载入的时候,只有其清单文件中列举出来的资源文件会载入。这些缓存项都属于“CACHE:”区域,即默认的区域。另外两种区域是以”NETWORK:“和”FALLBACK:”头信息开始的。
NETWORK
“NETWORK:”区域标识了该URL中的资源从不缓存,总要通过网络获取。通常,会讲一些服务器的脚本资源放在“NETWORK:”区域中,而实际上该区域中的资源URL都只是URL前缀,用来标识以此URL前缀开头的资源都应该要通过网络加载。如果浏览器处于离线状态,这些资源都将获取失败。
“NETWORK:”区域中的URL还支持”*”通配符。该通配符标识对任何不在清单中的资源,浏览器都将通过网络加载。
FALLBACK
“FALLBACK:”区域中的清单项,每行都包含两个URL。第二个URL是指需要加载和存储在缓存中的资源,第一个URL是一个前缀。
任何能够匹配到该前缀的URL都不会缓存起来,但是可能的话,他们会从网络中载入。如果从网络中载入这样一个URL失败的话,就会使用第二个URL指定的缓存资源来代替,从缓存中获取。
应用点,比如比较大的资源文件,不应该缓存起来,这时候可以给出一些帮助文案代替。
一个更加复杂的缓存清单例子:
1 2 3 4 5 6 7 8 9 10 11 12 |
CACHE MANIFEST CACHE: index.html style.css init.js FALLBACK: videos/offline_help.html NETWORK: cgi/ |
缓存的更新
当一个Web应用从缓存中载入的时候,所有与之相关的文件也是直接从缓存中获取的。在线状态下,浏览器会异步检查清单文件是否有更新。如果有更新,新的清单文件以及清单中列举的所有文件都会下载下来重新保存到应用程序缓存中。
但是,浏览器只是检查清单文件,而不会去检查浏览器普通缓存的文件是否有更新。如果修改了一个缓存的js文件,并且想要该文件生效,就必须去更新下情感文件。由于应用程序所依赖的文件列表其实没有变化,因此最简单的方式就是更新版本号。
1 2 3 4 |
CACHE MANIFEST #xuanfengge Version 1(更改这个数字让浏览器重新下载这个文件) index.html init.js |
如果想要让Web应用从缓存中“删除”,就要在服务端删除清单文件,使得请求该文件的时候,返回HTTP 404无法找到的错误。同时修改HTML文件以便与该清单列表断开连接。
浏览器检查清单文件以及更新缓存的操作时异步的,可能是在缓存中载入应用之前,也有可能同时进行。因此,对于简单的Web应用,在更新清单文件之后,用户必须载入应用两次才能保证最新的版本生效:第一次是从缓存中载入老版本最后更新缓存,第二次才从缓存中载入最新的版本。
浏览器在更新缓存的过程中会触发一系列事件,可以通过注册处理程序来跟踪这个过程同时反馈给用户。如:
1 2 3 4 |
applicationCache.onupdateready = function(){ var reload = confirm("Have a new version. Reload now?"); if(reload) location.reload(); } |
该事件处理程序是注册在ApplicationCACHE对象上的,该对象是Window的applicationCACHE属性的值。支持应用程序缓存的浏览器会定义该属性。
处理应用缓存相关事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
// 显示状态消息 function status(msg){ document.getElementById("statusline").innerHTML = msg; console.log(msg); } // 每当在应用程序载入的时候,都会检查该清单文件, // 先触发 checking事件 window.applicationCache.onchecking = function(){ status("Checking for a new version.") return false; } // 如果清单文件没有改动,同时应用程序也已缓存。 // 触发noupdate事件,整个过程结束 window.applicationCache.onnoupdate = function(){ status("This version is up-to-date."); return false; } // 如果还未缓存应用程序,或清单文件有改动,那么浏览器会下载缓存清单中的所有资源。 // 触发downloading事件,开始下载 window.applicationCache.ondownloading = function(){ status("Downloading new version."); window.progresscount = 0; // 下载进度 return false; } // 在下载的过程中会间断性地触发progress事件,通常是在每个文件下载完毕的时候 window.applicatopnCache.onprogress = function(e){ var progress = ""; if(e && e.lengthComputable){ // progress事件:计算下载完成比例 progress = " " + Math.round(100 * e.loaded / e.total) + "%"; }else{ // 输出调用次数 progress = " (" + ++progresscount + ")"; } status("Downloading new version" + progress); return false; } // 当下载完成并且首次将应用程序下载到缓存中,会触发cached事件 window.applicationCache.oncached = function(){ status("This application is now cached locally."); return false; } // 当下载完成并将缓存中的应用程序更新后,会触发updateready事件 // 触发此事件的时候,用户看到的仍是老版本的应用程序 window.applicationCache.onupdateready = function(){ status("A new version has been downloaded. Reload to run it."); return false; } // 如果浏览器处于离线状态,检查清单列表失败,则会触发error事件 // 当一个为缓存的应用程序引入一个不存在的清单文件,也会触发error window.applicationCache.onerror = function(){ status("Couldn't load manifest or cache application."); return false; } // 如果一个缓存的应用程序引入一个不存在的情感文件,会触发obsolete事件 // 会将应用从缓存中移除,之后都不会从缓存而是通过网络来加载资源 window.applciationCache.onobsolete = function(){ status("This applciation is no loger cached."); return false; } |
事件触发
每次载入一个设置了manifest属性的HTML文件,浏览器都会触发checking事件,并通过网络载入该清单文件。不过之后,会随着不同的情况触发不同的事件。
1. 没有可用的更新
如果应用程序已经缓存并且清单文件没有改动,则浏览器会触发noupdate事件。
2. 有可用的更新
如果应用程序已经缓存了并且清单文件发生了改动,则浏览器会触发downloading事件,并开始下载和缓存清单文件中列举的所有资源。随着下载过程的进行,浏览器还会触发progress事件,在下载完成之后,会触发updateready事件。
3. 首次载入新的应用程序
如果还未缓存应用程序,如上所述,downloading事件和progress事件都会触发。但是当下载完成后,浏览器会触发cached事件而不是uodateready事件。
4. 浏览器处于离线状态
如果浏览器处于离线状态,无法检查清单文件,同时会触发error事件。如果一个为缓存的应用程序引用一个不存在的清单文件,浏览器也会触发error事件。
5. 清单文件不存在
如果浏览器处于在线状态,应用程序也已经缓存起来,但是清单文件返回404不存在,浏览器会触发obsolete事件,并将该应用程序从缓存中移除。
除了使用事件处理程序之外,还可以使用applicationCache.status属性来查看当前缓存状态。该属性有6个可能的属性值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
应用程序没有设置manifest属性:未缓存 ApplicationCache.UNCACHED(0) 清单文件已经检查完毕,并且已经缓存了最新的应用程序 ApplicationCache.IDLE(1) 浏览器正在检查清单文件 ApplicationCache.CHECKING(2) 浏览器正在下载并缓存清单中列举的所有文件 ApplicationCache.DOWNLOADING(3) 已经下载和缓存了最新版的应用程序 ApplicationCache.UPDATEREADY(4) 清单文件不存在,缓存将被清除 ApplicationCache.OBSOLETE(5) |
还有65行的applciationCache 应该是applicationCache ,不好意思,我是一步一步从console中发现的。并且愉快的玩坏了你的评论框。
23行代码的function 写成funciton了
1155665 一闪一闪亮晶晶
30行代码的 applicationCache 写成了applicatopnCache
已更新,多谢