3分鐘掌握應(yīng)用緩存方案

當(dāng)談到現(xiàn)代的 Web 開發(fā)和離線訪問時夭禽,應(yīng)用緩存(Application Cache)是一個重要的話題渐夸。應(yīng)用緩存提供了一種在離線狀態(tài)下訪問網(wǎng)頁的機(jī)制的畴,使用戶可以在沒有網(wǎng)絡(luò)連接的情況下繼續(xù)瀏覽網(wǎng)站喻鳄。

應(yīng)用緩存

下面是設(shè)置應(yīng)用緩存的基本步驟:

  1. 在你的 HTML 文件的 <html> 標(biāo)簽中,添加一個 manifest 屬性遇绞,指向描述緩存資源的 .appcache 文件。例如:
<!DOCTYPE html>
<html manifest="example.appcache">
...
</html>
  1. 創(chuàng)建一個 .appcache 文件燎窘,并在其中列出需要緩存的資源摹闽。該文件的擴(kuò)展名通常為 .appcache,但實際上可以使用任何擴(kuò)展名褐健。例如付鹿,你可以創(chuàng)建一個名為 example.appcache 的文件,并添加以下內(nèi)容:
CACHE MANIFEST
# Version 1.0.0

CACHE:
/css/styles.css
/js/main.js
/images/logo.png

NETWORK:
*

FALLBACK:
/offline.html

CACHE: 部分列出你希望緩存的文件路徑。在上述示例中舵匾,CSS 文件俊抵、JavaScript 文件和圖像文件都會被緩存。

NETWORK: 部分指定哪些資源需要在線獲取坐梯,使用 * 表示所有資源都需要在線獲取徽诲。

FALLBACK: 部分定義了離線時應(yīng)該提供的替代頁面。在上述示例中吵血,如果用戶離線并且訪問了一個未緩存的頁面谎替,將會顯示 /offline.html 頁面作為替代。

  1. 將 .appcache 文件上傳到你的服務(wù)器践瓷,并確痹合玻可通過網(wǎng)址訪問到它。

  2. 當(dāng)用戶首次訪問你的網(wǎng)頁時晕翠,瀏覽器將會下載并緩存 .appcache 文件中列出的資源喷舀。

  3. 在接下來的訪問中,瀏覽器將檢查 .appcache 文件是否有更新淋肾。如果有更新硫麻,瀏覽器將下載新的資源并更新緩存。

然而樊卓,應(yīng)用緩存已經(jīng)被廢棄拿愧,現(xiàn)代的離線緩存方案主要包括使用 Service Worker 和瀏覽器的 Cache Storage API。

應(yīng)用緩存的問題

應(yīng)用緩存在過去使用廣泛碌尔,但它存在一些問題浇辜,因此被廢棄。其中一些問題包括:

  1. 更新困難:缺乏靈活性唾戚,難以更新緩存的資源柳洋。一旦緩存的資源發(fā)生變化,需要等到緩存的 manifest 文件發(fā)生變化或緩存過期后才能獲取到更新的資源叹坦。

  2. 可繞過性:用戶可以手動清除瀏覽器的應(yīng)用緩存熊镣,從而繞過緩存并強(qiáng)制瀏覽器重新加載資源。

  3. 緩存限制:大小有限募书,通常只能緩存較小的資源绪囱。大型文件無法有效地緩存,限制了其在離線訪問中的應(yīng)用場景莹捡。

其他離線緩存方案

  1. Service Worker:一種在瀏覽器后臺運行的腳本鬼吵,可以攔截和處理網(wǎng)絡(luò)請求,從而使開發(fā)者能夠自定義緩存策略和離線訪問邏輯篮赢。開發(fā)者可以精確控制緩存的更新而柑、失效和資源獲取方式文捶。一般與Cache Storage API搭配使用,支持緩存用于緩存文件和其他資源媒咳。

  2. Cache Storage API:瀏覽器提供的 API粹排,用于管理和操作緩存。允許開發(fā)者以編程方式創(chuàng)建涩澡、檢索和刪除緩存苛秕,并將請求和響應(yīng)存儲在緩存中昌执。開發(fā)者可以更細(xì)粒度地控制緩存的操作珊擂,并實現(xiàn)自定義的緩存策略矢门。

這些現(xiàn)代的離線緩存方案提供了更強(qiáng)大和靈活的功能,使開發(fā)者能夠更好地控制網(wǎng)頁的離線訪問體驗粥帚。它們支持動態(tài)緩存胰耗、離線資源更新和更高級的緩存策略,同時也提供了更好的性能和用戶體驗芒涡。

Service Worker

以下是一個使用 Service Worker 實現(xiàn)離線緩存的示例代碼:

// 注冊 Service Worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('Service Worker 注冊成功:', registration);
      })
      .catch(error => {
        console.log('Service Worker 注冊失敗:', error);
      });
  });
}

// service-worker.js

const CACHE_NAME = 'my-cache';
const urlsToCache = [
  '/',
  '/styles.css',
  '/script.js',
  '/image.jpg'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        return cache.addAll(urlsToCache);
      })
  );
});

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

上述代碼首先在頁面中注冊了一個 Service Worker柴灯。在 service-worker.js 腳本中,我們在安裝階段緩存了一些資源费尽,并在請求攔截階段返回緩存的響應(yīng)赠群。

在使用Service Worker時,可能會遇到以下一些常見問題:

  1. 緩存更新問題:新的Service Worker可能無法立即激活并替換舊的Service Worker旱幼,導(dǎo)致緩存更新不及時查描。可以通過在Service Worker中監(jiān)聽activate事件柏卤,并在其中清理舊的緩存來解決此問題冬三。
self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // 過濾出舊的緩存名稱
          return cacheName !== 'my-cache';
        }).map(function(cacheName) {
          // 刪除舊的緩存
          return caches.delete(cacheName);
        })
      );
    })
  );
});
  1. 緩存一致性問題:當(dāng)更新Web應(yīng)用的靜態(tài)資源時,由于瀏覽器的緩存機(jī)制缘缚,可能會導(dǎo)致新的資源無法及時生效长豁。可以通過在資源的URL中添加版本號或哈希值忙灼,以及在Service Worker中更新緩存策略來解決此問題。
// 在資源的URL中添加版本號或哈希值
const staticResources = [
  '/styles.css?v=1.0',
  '/script.js?v=1.0'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('my-cache')
      .then(function(cache) {
        return cache.addAll(staticResources);
      })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        if (response) {
          return response;
        }
        
        // 更新緩存策略
        return fetch(event.request)
          .then(function(networkResponse) {
            if (networkResponse.ok) {
              // 將新的響應(yīng)添加到緩存中
              caches.open('my-cache')
                .then(function(cache) {
                  cache.put(event.request, networkResponse.clone());
                });
            }
            
            return networkResponse;
          });
      })
  );
});
  1. HTTPS限制:Service Worker只能在使用HTTPS協(xié)議的網(wǎng)站上使用钝侠,這是出于安全考慮该园。在開發(fā)環(huán)境中,可以使用localhost或自簽名證書來進(jìn)行測試帅韧。

  2. 作用域限制:Service Worker的作用域是其所在的文件夾及其子文件夾里初,因此需要確保Service Worker文件與要攔截的請求在同一目錄或子目錄下。

  3. 生命周期管理:Service Worker具有自己的生命周期忽舟,需要注意其注冊双妨、安裝淮阐、激活和更新等過程,并合理處理這些事件以確保正確的功能和更新刁品。

  4. 瀏覽器兼容性:盡管大多數(shù)現(xiàn)代瀏覽器都支持Service Worker泣特,但在一些舊版本的瀏覽器中可能存在兼容性問題,因此需要進(jìn)行兼容性測試和降級處理挑随。

Cache Storage API

以下是一個使用 Cache Storage API 進(jìn)行離線緩存的示例代碼:

// 打開或創(chuàng)建一個名為 "my-cache" 的緩存
caches.open('my-cache')
  .then(cache => {
    // 緩存所需的資源
    return cache.addAll([
      '/',
      '/styles.css',
      '/script.js',
      '/image.jpg'
    ]);
  });

// 攔截請求并返回緩存的響應(yīng)
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        return response || fetch(event.request);
      })
  );
});

上述代碼通過 caches.open 方法打開或創(chuàng)建一個名為 "my-cache" 的緩存状您,并使用 cache.addAll 方法緩存指定的資源。在請求攔截階段兜挨,我們使用 caches.match 方法查找匹配的緩存響應(yīng)膏孟,并返回緩存的響應(yīng)或繼續(xù)從網(wǎng)絡(luò)獲取。

寫在最后

總結(jié)起來拌汇,應(yīng)用緩存在過去曾經(jīng)是一種常見的離線訪問解決方案柒桑,但由于其固有的問題,如更新困難噪舀、可繞過性和緩存限制魁淳,現(xiàn)代的 Web 開發(fā)更傾向于使用其他離線緩存方案。其中傅联,Service Worker 和 Cache Storage API 是目前主流的離線緩存方案先改。隨著 Web 技術(shù)的不斷發(fā)展,我們應(yīng)該關(guān)注和采用最新的離線緩存方案蒸走,以確保我們的網(wǎng)站能夠適應(yīng)不斷變化的需求和用戶期望仇奶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市比驻,隨后出現(xiàn)的幾起案子该溯,更是在濱河造成了極大的恐慌,老刑警劉巖别惦,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狈茉,死亡現(xiàn)場離奇詭異,居然都是意外死亡掸掸,警方通過查閱死者的電腦和手機(jī)氯庆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扰付,“玉大人堤撵,你說我怎么就攤上這事∮疠海” “怎么了实昨?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盐固。 經(jīng)常有香客問我荒给,道長丈挟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任志电,我火速辦了婚禮曙咽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溪北。我一直安慰自己桐绒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布之拨。 她就那樣靜靜地躺著茉继,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚀乔。 梳的紋絲不亂的頭發(fā)上烁竭,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音吉挣,去河邊找鬼派撕。 笑死,一個胖子當(dāng)著我的面吹牛睬魂,可吹牛的內(nèi)容都是我干的终吼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氯哮,長吁一口氣:“原來是場噩夢啊……” “哼际跪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喉钢,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤姆打,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肠虽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幔戏,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年税课,在試婚紗的時候發(fā)現(xiàn)自己被綠了闲延。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡韩玩,死狀恐怖垒玲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啸如,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布氮惯,位于F島的核電站叮雳,受9級特大地震影響想暗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帘不,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一说莫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寞焙,春花似錦储狭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呛牲,卻和暖如春刮萌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背娘扩。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工着茸, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琐旁。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓涮阔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親灰殴。 傳聞我的和親對象是個殘疾皇子敬特,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

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