HTML5之离线缓存的方法

28008次浏览

前言

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

暂时写到这里,欢迎交流!

相关文章: