前言
前几天,看到张鑫旭大神写了一篇关于离线缓存的技术的文章。我正好前段时间也用到了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/
暂时写到这里,欢迎交流!