首页 > 其他分享 >使用 jQuery Mobile 与 HTML5 开发 Web App (十七) —— HTML5 离线缓存

使用 jQuery Mobile 与 HTML5 开发 Web App (十七) —— HTML5 离线缓存

时间:2023-05-12 22:31:37浏览次数:56  
标签:jQuery 文件 缓存 浏览器 离线 更新 manifest HTML5


本文要介绍的,是 HTML5 离线网络应用程序的特性,离线网络应用程序在 W3C 中的实际名称是 "Offline Web applications" ,也称离线缓存。当用户打开浏览器时,浏览器会将一个列表中指定的资源都下载并储存在本地。下次当用户再访问这个网络程序时,浏览器会自动引用本地缓存中 相应的文件,而不会再从网络下载这些资源。不管离线网络应用程序是否专为 Web Apps 而设,但这对于 Web Apps 来说无疑是个非常实用的特性,它使到 Web Apps 相对于原生 Apps 的一个重要劣势 —— 高度依赖网络,得以大大减缓。开发者可以利用这个特性把 Web Apps 中的元素缓存到本地端,使到 Web Apps 可以脱机工作,即使是需要联网工作的 Apps ,也可以缓存部分文件到本地端,减少带宽占用,这样 Web Apps 相对于原生 Apps 就更加具有优势了。下面正式开始介绍这个特性。

一. 离线网络应用程序基础

离线网络应用程序的核心是一个 content type (内容类型) 为 cache-manifest 的文本文件。这个文件保存了应用程序中需要离线存储的文件(HTML, CSS, JavaScript, 图片等)。举一个简单的例子,若一个应用程序由以下文件组成:

  • index.html
  • demo.css
  • demo.js
  • logo.png

index.html 为主页,其他文件是主页中引用的资源,如果我们需要离线缓存这个应用程序,需要在 index.html 的同级目录下增加一个 manifest 文件,并命名为 .manifest 后缀文件,而文件中的内容可以这样编写:



CACHE MANIFEST
./index.html
./demo.css
./demo.js
./logo.png



 



 

可以看出,以上文件的路径是相对路径,这里是相对于 manifest 文件而言的。当然,你也可以使用绝对路径,这并不影响 manifest 的使用。

 

manifest 文件的编写很简单,但启用离线缓存还需一些步骤。首先是需要把 manifest 文件和应用程序关联起来,即把页面指向缓存名单,方法是为 html 标签指定 manifest 值,例如:

<html manifest="demo.manifest">



 



其中 demo.manifest 是例子中编写的 manifest 列表文件。

 

小提示:若应用程序中有多个页面,则每个页面都需要与 manifest 关联起来。

 

接着,开发者必须给 manifest 文件指定 text/cache-manifest 内容类型,这样浏览器才能识别它。关于具体的方法,如果你的服务器支持 .htaccess ,可以在 .htaccess 中写入以下语句:



AddType text/cache-manifest .manifest



 



这样做可以把 text/cache-manifest 的 MIME 类型和 .manifest 文件关联起来。当然,可能开发者并没有 .htaccess 的编写权限,但实际上,开发者可以使用另外一些更实用的方法达到目的。因为在实际的项目开发中,应用程序中的文件数量不会只像上例中仅有的 4 个,如果有很多的文件需要缓存,每个文件都需要手动写入 manifest 文件实在比较费时,更麻烦的是,每次改动这些文件都必须相应地改动 manifest 文件,因此 Kayo 更加建议开发者使用后台脚本直接获取需要缓存的文件并写入一个 manifest 列表,Kayo 熟悉的后台脚本是 PHP ,在 PHP 中,可以直接在代码中设置 MIME 类型,这样就不需要配置 Web 服务来完成对 manifest 的支持了。至于具体如何使用 PHP 编写 manifest ,会在下面详细介绍。

二. 浏览器支持

关于离线网络应用程序在现代浏览器中都已经实现完整的支持,IE 则完全不支持。具体如下:

Chrome 4+ , Firefox 3.5+ , Safari 4+ 和 Opera 10.6+

三. 白名单

默认情况下,开发者会为应用程序中所有文件指定缓存,但实际上,仍有一些资源可能需要强制取消缓存,即必须访问网络资源,离线时该资源不可用。为元 素强制取消缓存可以在 manifest 文件中使用关键字 NETWORK: 。在 NETWORK: 关键字下添加文件的列表,这些文件会强制取消缓存,而这个文件列表就称为白名单 (Whitelist) 。实际上,对于需要缓存的资源也是有关键字的,这个关键字是 EXPLICIT: ,但所有资源列表的开头如果没有添加关键字,默认都会被认为在 EXPLICIT: 关键字的列表下,因此需要缓存的资源列表开头可以忽略不写关键字(如上例)。

 

例如,对上例进行扩展,把 logo.png 添加到白名单,可以这样编写 manifest 文件。



CACHE MANIFEST
./index.html
./demo.css
./demo.js
 
NETWORK:
./logo.png



 



四. 备选名单

备选名单是对于白名单的补充,在白名单中,没有联网时,资源不能加载,这样会导致页面出现错误,如上例中,"logo.png" 被设置为白名单,如果用户离线浏览该应用程序,会出现一个损坏的图片链接,为了避免这种情况,可以使用 FALLBACK: 指定一个备选名单,备选名单中需要为一个资源准备两个文件,若能正常联网,会引用第一个文件,离线时则引用第二个文件,关于这个特点,有一个很实用的应用 —— 表明程序是离线工作还是联网工作,在不同的状态下引用不同的图片即可方便地表明状态。接下来 Kayo 继续扩展上例,为 logo.png 指定一个离线时的替换图片 backup.png 。



CACHE MANIFEST
./index.html
./demo.css
./demo.js
 
FALLBACK:
./logo.png ./backup.png



 



五. 更新 manifest

似乎,经过上面三个步骤后,应用程序的离线缓存已经很好的工作了。但有一个很重要的问题仍需注意 —— 根据离线缓存的工作原理,当用户第一次使用应用程序时,浏览器会根据 manifest 文件里的列表下载指定的资源,在下次使用该应用程序时,浏览器会自动加载这些资源的副本,那么假如开发者修改了程序,浏览器仍旧会加载本地的资源,因此我 们需要给浏览器一个提示,程序已经更新。

 

那么什么时候浏览器会更新本地缓存呢?

只有当 manifest 修改后浏览器才会重新下载 manifest 中所有指定需要离线缓存的文件。而检测 manifest 是否修改过是对 manifest 文件的内容逐个字符进行比较,包括注释和空行。当然,大多情况下,修改程序时并不会影响主要的文件,所以 manifest 中的文件列表也不会有改动,因此需要改动 manifest 以通知浏览器程序已更新的最好办法是修改注释,开发者可以在 manifest 文件中添加一行注释,比如说是程序的版本号,当程序更新后同时修改 manifest 文件中这个版本号,浏览器就会判定程序已经更新,自动重新下载所有需要离线缓存的资源。例如,把上例改成:



CACHE MANIFEST
# version 1.0
./index.html
./demo.css
./demo.js
 
FALLBACK:
./logo.png ./backup.png



 



 

需要注意的是,"CACHE MANIFEST"是必要行,并且必须在 manifest 文件中的第一行。这样下次更改程序后同时修改 manifest 的程序版本号,浏览器就可以判定程序更新了。

手动更新缓存

当然,为了能更精确地控制程序更新,最好是使用手动方法更新缓存,离线网络应用程序规范中也提供了相应的手动更新缓存的方法。开发者可以使用 window.applicationCache.update() 方法手动更新缓存,为了更准确地判断是否需要更新,开发者可以先检测 window.applicationCache.status 的值,若其值为 "UPDATEREADY" (即浏览器检测到 manifest 已被修改), 可以调用 window.applicationCache.update() 方法更新缓存。例如:



if ( window.applicationCache.status == window.applicationCache.UPDATEREADY ){
    window.applicationCache.update();
}


 



六. 使用 PHP 脚本编写 manifest 文件

如上面所说,使用脚本编写 manifest 文件可以同时解决 manifest 文件扩展名与 MIME 类型关联起来,还可以自动列出缓存文件。具体的编写如下:

header('Content-Type: text/cache-manifest');
echo "CACHE MANIFEST\n";
 
$allHashes = ""; // 创建一个字符串保存文件的 md5 值
 
$dir = new RecursiveDirectoryIterator(".");
foreach(new RecursiveIteratorIterator($dir) as $file){ // 获取当前目录并遍历文件
    if( $file->IsFile() && // 判断获取内容为文件
        $file->getFilename() != "manifest.php" && // "manifest.php" 不缓存
        $file->getFilename() != "logo.png" && // 备选资源不缓存
        $file->getFilename() != "offline.png" &&
        !strpos( $file, '/.' ) &&
        substr( $file->getFilename(), 0, 1 ) != "."){
 
        echo "./" . $file->getFilename() . "\n";
        $allHashes .= md5_file($file); // 把每一个缓存的文件的 md5 值连接起来
    }
  
}
  
echo "FALLBACK:\n"; // 输出备选名单
echo "./logo.png ./offline.png\n";
 
echo "# " . md5($allHases) ."\n"; // 把连接起来的 md5 值重新计算一个 md5(因为连接所得的字符串过于冗长)



 



 

在这个脚本中,获取了应用程序的目录并把目录中的文件逐个添加到缓存列表,同时在这个过程中排除如 "manifest.php" 和备选资源等文件,并且,对每一个缓存的文件计算 md5 值,把这些值连接起来后重新计算一个 md5 并输出到一行注释中,这样缓存的文件只要有一个发生了改变,都会影响这行注释,从而使到整个 manifest 文件发生改变,这样就并不需要在更新程序后手动修改 manifest 文件。可以看出,如果需要缓存的文件很多时,该方法将会十分方便,并且更新程序后 manifest 文件也会被自动修改。当然,这只是使用脚本编写 manifest 的其中一种方式,开发者应视具体情况而制定相应的脚本。

七. 关于离线网络应用程序的属性、方法和事件

在 “手动更新缓存” 中,Kayo 提到了一个对象 window.applicationCache ,这个对象中包含了与离线网络应用程序相关的属性、方法和事件,除了上面涉及到的 status 属性和 update() 方法外,还有其他的相关内容,下面开始对它们进行详细介绍。

1. 属性

window.applicationCache 对象中具有一个属性 status ,该状态会根据当前的缓存状态显示不同的值和状态编号,具体的属性值如下:

  • UNCACHED 未开始缓存状态。 状态编号:0
  • IDLE 空闭状态。 状态编号:1
  • CHECKING 正在检查 manifest 文件是否存在。 状态编号:2
  • DOWNLOADING 正在下载缓存文件。 状态编号:3
  • UPDATEREADY 更新下载已完成,等待更新状态。 状态编号:4
  • OBSOLETE 废弃状态。 状态编号:5

2. 方法

接着,是相关的方法,具体如下:

  • update() 检测与文档关联的 manifest 文件是否有修改,如果有修改,则更新缓存。若 manifest 文件不存在或该缓存已废弃,则会抛出一个 InvalidStateError 错误。
  • abort() user agent 会发出一个信号给当前的缓存对象,中止应用缓存的下载,如果页面没有使用离线网络应用程序,那么在尝试发出信号后该方法不会再执行任何操作。
  • swapCache() 手动执行本地缓存更新,并且只能在 updataReady 事件触发时在事件回调函数中调用。但需要注意该方法不会立即更新缓存文件,仍需要刷新页面才生效。若文档关联的 manifest 文档不存在,会抛出一个 InvalidStateError 错误。

3. 事件

除了属性和方法,window.applicationCache 对象还会根据一些情况在其身上触发一些事件,开发者应该了解这些事件,根据所触发的事件,可以了解一个正在运作的离线缓存的工作情况,然后根据不同的情况作出适当的处理。

  • checking 浏览器在检测到 html 标签上有 manifest 属性后,会检查相关联的 manifest 文件是否存在,同时触发 checking 事件。
  • noupdate 在检测到 manifest 没有更新(即没有修改)时触发。
  • downloading 缓存下载时触发。
  • progress 下载进度(阶段性事件)。
  • cached 已根据 manifest 文件中指定的要求下载相应的资源。
  • updateready 更新时,已根据 manifest 文件中指定的要求重新下载相应的资源。
  • obsolete manifest 文件请求发生 404 或 410 错误时触发,发生此事件表明该缓存已被删除。
  • error 以下四种情况都会触发 error 事件:1. manifest 文件请求发生 404 或 410 错误; 2. manifest 文件没有修改,但页面无法正确引用 manifest ;3. 根据 manifest 文件更新资源时发生致命错误(如上面提到的 InvalidStateError 错误);4. 当资源正在更新时 manifest 文件被修改。

这里 Kayo 需要指出一点,以上这些事件并不会在一个缓存过程中全部触发,如 error(前三种情况) , updateready , obsolete , noupdate , cached 均为一个缓存过程中的最终事件,在一次缓存过程中只会出现其中一个。又如 cached 事件,必须要有下载资源并且在完成后才触发,即第二次打开页面并且 manifest 没有修改是不会触发 cached 事件(没有下载资源),开发者应仔细注意每个事件的触发时刻,判断在不同情况下应该利用何种事件。

 

这个例举一个例子,使用 addEventListener 监听 cached 事件,检测到 cached 事件发生时弹出提示,即代表离线资源已经下载完成。



if(window.applicationCache) {
 
    window.applicationCache.addEventListener('cached', function(){
        alert('cached');
    }, true);
 
}



 



八. 完整实例 Demo

为了使读者更好的理解离线网络应用程序的具体使用,这里会把上面逐步扩展的例子写成完整 Demo (为了简化例子结构,这里只使用 addEventListener 监听事件,请使用 Chrome, Firefox 等现代浏览器浏览 Demo )。

完整 Demo

 


标签:jQuery,文件,缓存,浏览器,离线,更新,manifest,HTML5
From: https://blog.51cto.com/u_8895844/6272284

相关文章

  • jQuery 3.7.0 发布,提升操作性能
    jQuery3.7.0已正式发布。更新内容包括修复错误、引入新方法,以及提升性能。其中值得关注的一项变化是放弃了长期使用的选择器引擎Sizzle—— jQuery不再依赖于作为单独项目的Sizzle。开发者表示他已经将Sizzle移动至jQuery内部,将其代码直接放到jQuery核心。据称......
  • CSS、JS、jQuery中选择器总结
    CSS、JS、jQuery中选择器总结CSS中选择器:1.元素选择器:根据标签名来选中指定元素语法:标签名{}2.将被指定的元素设为不同样式ID选择器,根据元素的ID属性值选中一个元素语法:#ID属性值{}设置了重复的ID也可设置同样的效果3.class标签属性;每个标签都有和ID类似但其可以重复使用......
  • 分享Python采集88个html5代码,总有一款适合您
    分享Python采集88个html5代码,总有一款适合您Python采集的88个html5代码下载链接:https://pan.baidu.com/s/1wJzpYBlHIGtNgTisJwCQ6Q?pwd=yr96提取码:yr96imgplay-基于canvas的图片序列播放jQuery插件基于HTML5Canvas和Rebound动画的Loading加载动画特效超酷创意分段式SVG文字动画特......
  • MySQL好玩新特性:离线模式
    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:Yejinrong/叶金荣文章来源:GreatSQL社区原创继续吹MySQL8.0~在以前,当需要对MySQL数据库进行维护操作时,通常需要先进行主从切换,然后修改设置并......
  • CentOS6离线安装lnmp
    服务器无法访问外网,采用离线安装的方式安装lnmp之前尝试了很多次,nginx和mysql都安装成功了,php一直安装不成功 今天排查报错信息,用yuminstalllibicu-devel命令安装libicu,提示安装不成功,查了一下本地源,发现有对应的rpm包,但是yum命令找不到。之前挂载本地镜像挂载了两个光盘,发......
  • HTML5基础day3
    关于HTML5第三天的学习内容1.audio音频文件 运行后可在网页中展现音频文件且可以播放注意:音频元素缺失controls属性会导致页面效果丢失,变成空白2.HTML5结构元素一般的页面布局由页面头部、页面主体、页面底部构成,分别通过代码header、section、footer来实现  3.表单......
  • html5 3.0 表单
    表单的定义:多个输入框,以表格的形式展示表单常用在网页登录和注册功能中表单的元素属性:<inputtype="text"name="  ”value=" "/>type;指定当前元素的类型value:所见即所得name:提交到后端服务器的值文本框<inputtype="text"value=""/>用户在页面中输入的值明文显示;valuce="......
  • jquery ui dialog 遮拦 select的解决方法
    <scripttype="text/javascript"src="/js/jquery.bgiframe.min.js"></script>  1.    引用以上JS代码。 注意:jquery与jquery.bgiframe插件的对应版本  2.    JS代码加入红色部分         $("#dialog-editor").dialog({ bgiframe:true, ......
  • Google Chrome浏览器离线安装包下载方式
    GoogleChrome是应用很广泛的浏览器,默认是在线安装模式。如果网络速度很慢,或者没有网络的时候,就需要离线安装包了。32位Chrome离线包下载:http://www.google.cn/chrome/browser/desktop/index.html?standalone=164位Chrome离线包下载:http://www.google.cn/chrome/brow......
  • Jquery操作select汇总
    转载:http://www.cnblogs.com/pepcod/archive/2012/07/03/JavaScript.html//Query获取Select选择的Text和Value:$("#select_id").change(function(){//code...});//为Select添加事件,当选择其中一项时触发varcheckText=$("#select_id").find("option:selected&qu......