前言
前几天,看到张鑫旭大神写了一篇关于离线缓存的技术的文章。我正好前段时间也用到了html5的manifest,虽然不是什么新的技术,但是感觉和张大神理解的有点偏差。张大神说html5 manifest要前后端配合使用。其实,目前html5 manifest也可以纯前端开发,不需要后端和服务器端的配合。 ###html5 manifest纯前端开发是如何做的呢? 之前的写法是
*<html lang="en" manifest="haorooms.manifest"> 这种写法要在web 服务器上配置正确的 MIME-type,即 “text/cache-manifest”。
例如对Apache服务器进行配置的时候,需要找到 {apache_home}/conf/mime.type这个文件(.htaccess),并在文件最后添加如下所示代码:
*text/cache-manifest .manifest
等等。
新的写法:
*<html manifest="haorooms.appcache"> 扩展名”.appcache”为后缀,不需要我们再进行服务器端的配置了。就可以纯前端的进行离线缓存的操作。 ###介绍一下Manifest文件 接下来详细说说manifest的细节,一个典型的manifest文件代码结构像下面这样:
*CACHE MANIFEST *#version 1.2.2
*CACHE: *#css *http://www.haorooms.com/theme/assets/style.css *#js *http://www.haorooms.com/theme/assets/js/main.js
*#img *http://static.hyb.dev.ipo.com/css/wifi/pc/images/logo-fk1.png *http://static.hyb.dev.ipo.com/css/wifi/images/favicon.ico
*NETWORK:
** *FALLBACK:
- /404.html
manifest文件,基本格式为三段:
*CACHE, *NETWORK, *FALLBACK,
其中NETWORK和FALLBACK为可选项。 而第一行CACHE MANIFEST为固定格式,必须写在前面。 以#号开头的是注释,一般会在第二行写个版本号,用来在缓存的文件更新时,更改manifest的作用,可以是版本号,时间戳或者md5码等等。
下面对这三段简要介绍一下:
*CACHE:(必须)标识出哪些文件需要缓存,可以是相对路径也可以是绝对路径。 *NETWORK:(可选)这一部分是要绕过缓存直接读取的文件,可以使用通配符*。
例如:下面的代码 “login.php” 永远不会被缓存,且离线时是不可用的:
*NETWORK:login.php
可以使用星号来指示所有其他资源/文件都需要因特网连接。
*FALLBACK:(可选)
指定了一个后备页面,当资源无法访问时,浏览器会使用该页面。该段落的每条记录都列出两个 URI
*第一个表示资源, 第二个表示后备页面。
两个 URI 都必须使用相对路径并且与清单文件同源。可以使用通配符。
例如:下面的例子中,如果无法建立因特网连接,则用 “404.html” 替代 /html5/ 目录中的所有文件。
*FALLBACK:/html5/ /404.html
###如何更新缓存 如下三种方式,可以更新缓存:
*一、更新manifest文件:给manifest添加或删除文件,都可更新缓存,如果我们更改了js,而没有新增或删除,前面例子中注释中的版本号、时间戳或者md5码等进行修改,都可以很好的用来更新manifest文件 *二、通过javascript操作:html5中引入了js操作离线缓存的方法,下面的js可以手动更新本地缓存。 *window.applicationCache.update(); *三、清除浏览器缓存:如果用户清除了浏览器缓存(手动或用其他一些工具)都会重新下载文件。
###注意事项
*1、浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。 *2、如果manifest文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。 *3、引用manifest的html必须与manifest文件同源,在同一个域下。 *4、FALLBACK中的资源必须和manifest文件同源。 *5、当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。 *6、站点中的其他页面即使没有设置manifest属性,请求的资源如果在缓存中也从缓存中访问。 *7、当manifest文件发生改变时,资源请求本身也会触发更新。
###html5 manifest的问题
假如页面中使用了manifest离线缓存,动态数据我们要用ajax请求获得,不然数据不会更新。
###借助Service Worker和cacheStorage缓存及离线开发 可以参考张鑫旭大神的文章,这里引用一下其固定套路:
一、页面上注册一个Service Worker,例如:
- if (‘serviceWorker’ in navigator) {
- navigator.serviceWorker.register(‘./sw-demo-cache.js’);
- }
二、sw-demo-cache.js这个JS中复制如下代码:
*var VERSION = ‘v3’; * *// 缓存 *self.addEventListener(‘install’, function(event) {
- event.waitUntil(
- caches.open(VERSION).then(function(cache) {
- return cache.addAll([
- ’./start.html’,
- ’./static/jquery.min.js’,
- ’./static/mm1.jpg’
- ]);
- })
- ); *}); * *// 缓存更新 *self.addEventListener(‘activate’, function(event) {
- event.waitUntil(
- caches.keys().then(function(cacheNames) {
- return Promise.all(
- cacheNames.map(function(cacheName) {
- // 如果当前版本和缓存版本不一致
- if (cacheName !== VERSION) {
- return caches.delete(cacheName);
- }
- })
- );
- })
- ); *}); * *// 捕获请求并返回缓存数据 *self.addEventListener(‘fetch’, function(event) {
- event.respondWith(caches.match(event.request).catch(function() {
- return fetch(event.request);
- }).then(function(response) {
- caches.open(VERSION).then(function(cache) {
- cache.put(event.request, response);
- });
- return response.clone();
- }).catch(function() {
- return caches.match(‘./static/mm1.jpg’);
- })); *});
三、把cache.addAll()方法中缓存文件数组换成你希望缓存的文件数组。
张鑫旭的方法地址是:http://www.zhangxinxu.com/wordpress/2017/07/service-worker-cachestorage-offline-develop/