服务人员:如何更新服务器上的文件更改缓存?

服务人员:如何更新服务器上的文件更改缓存?

问题描述:

你使用什么样的缓存策略?我阅读了离线手册,最简单的策略是缓存静态内容,并省略API调用。服务人员:如何更新服务器上的文件更改缓存?

这一战略似乎是这样的:

  1. 检查请求是否已在缓存中
  2. 如果不加要求,响应对缓存
  3. 返回响应

如果在服务器端文件已更改,如何更新缓存?目前客户端总是获得缓存的结果。

这里是我的缓存策略代码:

// You will need this polyfill, at least on Chrome 41 and older. 
 
importScripts("serviceworker-cache-polyfill.js"); 
 

 
var VERSION = 1; 
 

 
var CACHES = { 
 
    common: "common-cache" + VERSION 
 
}; 
 

 
// an array of file locations we want to cache 
 
var filesToCache = [ 
 
    "font-cache.html", 
 
    "script.js", 
 
]; 
 

 
var neededFiles = [ 
 
    "index.html" 
 
]; 
 

 
var errorResponse = function() { 
 

 
    return new Response([ 
 
      "<h2>Failed to get file</h2>", 
 
      "<p>Could not retrive response from cache</p>" 
 
     ].join("\n"), 
 
     500 
 
    ); 
 
}; 
 

 
var networkFetch = function(request) { 
 

 
    return fetch(request).then(function(response) { 
 

 
     caches.open(CACHES["common"]).then(function(cache) { 
 

 
      return cache.put(request, response); 
 
     }); 
 

 
    }).catch(function() { 
 
     console.error("Network fetch failed"); 
 
     return errorResponse(); 
 
    }); 
 
} 
 

 
this.addEventListener("install", function(evt) { 
 
    evt.waitUntil(
 
     caches.open(CACHES["common"]).then(function(cache) { 
 

 
      // Cache before 
 
      cache.addAll(filesToCache); 
 
      return cache.addAll(neededFiles); 
 
     }) 
 
    ); 
 
}); 
 

 
this.addEventListener("activate", function(event) { 
 

 
    var expectedCacheNames = Object.keys(CACHES).map(function(key) { 
 
     return CACHES[key]; 
 
    }); 
 

 
    console.log("Activate the worker"); 
 

 
    // Active worker won"t be treated as activated until promise resolves successfully. 
 
    event.waitUntil(
 
     caches.keys().then(function(cacheNames) { 
 
      return Promise.all(
 
       cacheNames.map(function(cacheName) { 
 
        if (expectedCacheNames.indexOf() === 
 
         -1) { 
 
         console.log(
 
          "Deleting out of date cache:", 
 
          cacheName); 
 

 
         return caches.delete(cacheName); 
 
        } 
 
       }) 
 
      ); 
 
     }) 
 
    ); 
 
}); 
 

 
self.addEventListener("fetch", function(event) { 
 
    console.log("Handling fetch event for", event.request.url); 
 

 
    event.respondWith(
 

 
     // Opens Cache objects 
 
     caches.open(CACHES["common"]).then(function(cache) { 
 
      return cache.match(event.request).then(function(
 
       response) { 
 

 
       if (response) { 
 
        console.log("Found response in cache", response); 
 

 
        return response; 
 
       } else { 
 

 
        return networkFetch(event.request); 
 
       } 
 
      }).catch(function(error) { 
 

 
       // Handles exceptions that arise from match() or fetch(). 
 
       console.error(
 
        " Error in fetch handler:", 
 
        error); 
 

 
       return errorResponse(); 
 
      }); 
 
     }) 
 
    ); 
 
});

+0

服务器发送的事件是什么意思?当页面或资源得到更新时发送事件并更新缓存? –

你可能熟悉很大杰夫Posnick的解决方案 - sw-precache
策略使用的有:

  1. 咕嘟咕嘟正在生成服务工作者与校验
  2. 服务人员登记(用他自己的校验)
  3. 如果添加了文件/更新时,SW文件更改
  4. 文件
  5. 下一次访问时,SW会检查其校验和是否不同,因此它会使用更新后的文件再次注册本身

您可以通过后端自动执行此流程任何你想要的方式:)

this article

+0

这似乎是一个好方法,唯一的问题是自定义缓存逻辑如何适应这种方法? –

+0

您可以操作sw-precache并在其中引入不同的缓存策略。 有两个策略需要考虑:存储策略和服务策略。 本例中的存储策略是“正在安装”。通过一些小的附加更改,您可以更改 'self.addEventListener('install''到'self.addEventListener('push''),以更改为存储推送 您可以更改服务策略(在'fetch'事件) sw的基本模板是主文件夹中的service-worker.tmpl –

更好的形容这是我使用缓存的代码。它获取资源并缓存并提供服务。

this.addEventListener("fetch", function(event) { 
    event.respondWith(
    fetch(event.request).then(function(response) { 
     return caches.open("1").then(function(cache) { 
     return cache.put(event.request, response.clone()).then(function() { 
      return response 
     }) 
     }) 
    }).catch(function() { 
     return caches.match(event.request) 
    }) 
) 
}) 
+0

这种方法的问题是请求获取在接收超时之前可能需要一些未知时间,而且当您处于脱机模式时,有些时间直到返回响应,从用户的角度来看,这是不好的 –

您必须更改您的服务工作者文件。据Introduction to Service Worker

当用户浏览到您的网站时,浏览器会尝试重新下载在后台中定义的服务人员脚本文件。如果服务工作者文件中有一个字节的差异与目前的差异,则认为它是“新的”。

因此,即使您只需要更改静态资源,您也必须更新服务工作文件,以便注册更新缓存的新服务工作器。 (您需要确保在您的activate处理程序中删除以前的任何缓存。)@Karol Klepacki的答案提出了一种自动执行此操作的方法。

或者,您可以在服务工作人员自身中实施逻辑,以定期检查缓存资源的更改并适当更新条目。

+0

是的,你可以在我的工作文件中看到应该触发“激活”事件的版本,并且应该删除以前的缓存资源。问题是,在刷新的同一个选项卡内,从服务器请求工作者文件,但从未在客户端更新,直到关闭选项卡。 –