2015-05-29 160 views
2

你使用什麼樣的緩存策略?我閱讀了離線手冊,最簡單的策略是緩存靜態內容,並省略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

服務器發送的事件是什麼意思?當頁面或資源得到更新時發送事件並更新緩存? –

回答

3

你可能熟悉很大傑夫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 –

2

更好的形容這是我使用緩存的代碼。它獲取資源並緩存並提供服務。

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

這種方法的問題是請求獲取在接收超時之前可能需要一些未知時間,而且當您處於脫機模式時,有些時間直到返回響應,從用戶的角度來看,這是不好的 –

1

您必須更改您的服務工作者文件。據Introduction to Service Worker

當用戶瀏覽到您的網站時,瀏覽器會嘗試重新下載在後臺中定義的服務人員腳本文件。如果服務工作者文件中有一個字節的差異與目前的差異,則認爲它是「新的」。

因此,即使您只需要更改靜態資源,您也必須更新服務工作文件,以便註冊更新緩存的新服務工作器。 (您需要確保在您的activate處理程序中刪除以前的任何緩存。)@Karol Klepacki的答案提出了一種自動執行此操作的方法。

或者,您可以在服務工作人員自身中實施邏輯,以定期檢查緩存資源的更改並適當更新條目。

+0

是的,你可以在我的工作文件中看到應該觸發「激活」事件的版本,並且應該刪除以前的緩存資源。問題是,在刷新的同一個選項卡內,從服務器請求工作者文件,但從未在客戶端更新,直到關閉選項卡。 –

相關問題