瀏覽器緩存方案

HTTP響應頭的實現(xiàn)

如果一個網(wǎng)站中的某個文件是百年不變的坦康,那么肯定沒有必要打開網(wǎng)頁都重新獲取啊巍虫。我們可以設置HTTP返回頭的Cache-Control瞬逊。

  • max-age=31536000:過期時間(單位是秒)碱呼,最大不能超過一年,只要沒過期或者手動清除緩存就會使用緩存蔗牡。

  • no-cache:每次使用緩存之前颖系,向服務器對資源進行驗證。最終實現(xiàn)不使用緩存的過期資源的效果辩越。(不要理解為字面意思:不緩存)

  • no-store:不使用緩存

  • must-revalidate:如果設置了max-age嘁扼,在有效期內(nèi)會使用緩存,否則就需要進行驗證黔攒。所以可以結(jié)合使用Cache-Control: must-revalidate, max-age=60偷拔。

那么服務端怎么進行驗證呢?服務器第一次返回的響應頭中有一個ETag字段亏钩,該字段相當于一個標識,具體的生成邏輯由服務端決定欺旧。
然后客戶端之后的請求頭中會攜帶一個If-None-Match字段姑丑,這個字段就是那個標識。服務器通過對比這個標識判斷資源是否發(fā)生了更新辞友。

Expires VS max-age

在響應頭中有時還有一個expires字段栅哀,它和設置max-age一樣都是設置有效期的。不過expires字段直接指定過期時間称龙。而后者則是指定多長時間之后過期留拾。

expires: Mon, 24 Dec 2018 13:55:24 GMT
last-modified VS Etag

在響應頭中還有一個字段last-modified,它也可以用來做驗證鲫尊。那么它與Etag有什么區(qū)別呢痴柔?可以說Etag應該是更為精準的,last-modified最多精確到秒疫向,而Etag則是只要發(fā)生變化咳蔚,標識就會改變豪嚎。

last-modified: Thu, 01 Jan 1970 00:00:00 GMT

Service Workers

1、Service Workers是什么谈火?

Service Workers是瀏覽器在后臺獨立于網(wǎng)頁運行的腳本侈询,它可以支持離線體驗。有以下幾點注意事項:

  • 它是一種JavaScript 工作線程糯耍,不能直接訪問DOM

  • 服務工作線程是一種可編程網(wǎng)絡代理扔字,讓您能夠控制頁面所發(fā)送網(wǎng)絡請求的處理方式。

  • 它在不用時會被中止温技,并在下次有需要時重啟

  • 在開發(fā)過程中革为,可以通過 localhost 使用服務工作線程,但如果要在網(wǎng)站上部署服務工作線程荒揣,需要在服務器上設置 HTTPS篷角。

2、生命周期
  1. 首先需要在我們的網(wǎng)頁中注冊Service Workers系任。注冊會讓瀏覽器后臺執(zhí)行Service Workers的安裝步驟恳蹲。

  2. 在Service Workers的獨立腳本中,設置在安裝過程中要緩存的文件俩滥,如果所有文件都緩存成功則安裝成功嘉蕾;如果有任何一個失敗都將失敗,Service Workers就安裝失敗霜旧。

  3. 安裝完成就該激活了错忱,在這里我們對舊緩存進行管理。

  4. 激活之后挂据,服務工作線程將會對其作用域內(nèi)的所有頁面實施控制

接下來以清,我們詳細了解一下各個步驟的代碼寫法:

3、代碼實現(xiàn)

在頁面中注冊Service Workers崎逃,來啟動安裝掷倔。在register方法中告訴瀏覽器Service Workers腳本的路徑,這里是在根目錄下个绍,所以Service Workers接受該域下所有的fetch事件勒葱。

// 判斷瀏覽器對Service Workers的支持情況
if ('serviceWprker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/sw.js')
      .then(registration => {
        if (registration.waiting) {
          console.log('安裝完畢');
        }
      })
      .catch(err => {
        console.log(err);
      });
  });
}

接下來看一下Service Workers中的安裝過程,這里會監(jiān)聽一個install事件巴柿,在事件回調(diào)中又可以分為三部:

var CACHE_NAME = 'my-cache';
var cacheList = ['/', '/src/main.js'];
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(cacheList);
    })
  );
});
  • 打開緩存凛虽,這里需要傳入一個想要緩存的自定義名稱。

  • 緩存文件广恢,可以是一個由想要緩存的文件路徑組成的數(shù)組

  • 確認所有需要的資產(chǎn)是否緩存凯旋,event.waitUntil() 方法帶有 promise 參數(shù)并使用它來判斷安裝所花費的時間以及安裝是否成功。

在安裝完成之后,我們可能會想要一個對fetch事件的處理瓦阐,當監(jiān)聽到fetch請求時蜗侈,先匹配緩存中的內(nèi)容,如果有就返回緩存的內(nèi)容睡蟋,沒有則發(fā)起網(wǎng)絡請求踏幻。

self.addEventListener('fetch', event => {
  event.respondWith(
    caches
      .match(event.request)
      .then(response => response || fetch(event.request))
  );
});

這里如果想要連續(xù)緩存新的請求,可以處理fetch請求的響應并將其添加到緩存中戳杀。

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      if (response) {
        return response;
      }
      // 如果時新的請求就克隆一個請求
      var fetchRequest = event.request.clone();
      return fetch(fetchRequest).then(res => {
        // 校驗響應该面,對第三方資產(chǎn)(type)的請求不會添加到緩存
        if (!res || res.status !== 200 || res.type !== 'basic') {
          return res;
        }
        // 該響應是Stream,所以主體只能用一次信卡,需要克隆響應隔缀,一個發(fā)送給瀏覽器,一個保留在緩存中
        var responseToCache = res.clone();
        caches.open(CACHE_NAME).then(cache => {
          cache.put(event.request, responseToCache);
        });
        return res;
      });
    })
  );
});

接著看傍菇,當某個時候猾瘸,Service Workers需要更新了,應該有以下步驟:

  • 在用戶打開頁面的時候瀏覽器會嘗試在后臺重新下載定義了Service Workers的腳本丢习。如果有變化了就認為是更新了牵触。

  • 這時新的Service Workers就會啟動將觸發(fā)install事件,此時此刻舊的Service Workers還在控制著頁面咐低,新的Service Workers處于waitting狀態(tài)

  • 當前這個頁面關閉之后揽思,新的Service Workers就會占據(jù)控制權。

  • 新服務工作線程取得控制權后见擦,就會觸發(fā)其 activate 事件钉汗。

在 activate 回調(diào)中一般就是進行緩存管理,把舊的Service Workers清除掉鲤屡。先定義一個新的緩存百名單损痰,然后遍歷Service Workers所有的緩存,把不在白名單內(nèi)的刪除酒来。

self.addEventListener('activate', event => {
  // 白名單
  var cacheWhiteList = ['new-cache'];
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (cacheWhiteList.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末徐钠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子役首,更是在濱河造成了極大的恐慌,老刑警劉巖显拜,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衡奥,死亡現(xiàn)場離奇詭異,居然都是意外死亡远荠,警方通過查閱死者的電腦和手機矮固,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人档址,你說我怎么就攤上這事盹兢。” “怎么了守伸?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵绎秒,是天一觀的道長。 經(jīng)常有香客問我尼摹,道長见芹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任蠢涝,我火速辦了婚禮玄呛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘和二。我一直安慰自己徘铝,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布惯吕。 她就那樣靜靜地躺著惕它,像睡著了一般。 火紅的嫁衣襯著肌膚如雪混埠。 梳的紋絲不亂的頭發(fā)上怠缸,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音钳宪,去河邊找鬼揭北。 笑死,一個胖子當著我的面吹牛吏颖,可吹牛的內(nèi)容都是我干的搔体。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼半醉,長吁一口氣:“原來是場噩夢啊……” “哼疚俱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缩多,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呆奕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后衬吆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梁钾,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年逊抡,在試婚紗的時候發(fā)現(xiàn)自己被綠了姆泻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拇勃,靈堂內(nèi)的尸體忽然破棺而出四苇,到底是詐尸還是另有隱情,我是刑警寧澤方咆,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布月腋,位于F島的核電站,受9級特大地震影響峻呛,放射性物質(zhì)發(fā)生泄漏罗售。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一钩述、第九天 我趴在偏房一處隱蔽的房頂上張望寨躁。 院中可真熱鬧,春花似錦牙勘、人聲如沸职恳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽放钦。三九已至,卻和暖如春恭金,著一層夾襖步出監(jiān)牢的瞬間操禀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工横腿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留颓屑,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓耿焊,卻偏偏與公主長得像揪惦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子罗侯,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容