漸進(jìn)式Web應(yīng)用(PWA)的Service Worker緩存機(jī)制

一唐含、前言

近期在研究網(wǎng)頁(yè)緩存機(jī)制的時(shí)候?qū)W習(xí)了一下漸進(jìn)式 Web 應(yīng)用(PWA)中了 ServiceWorkers,并在 AWTK在線幫助文檔 中實(shí)踐應(yīng)用了一下秕硝,在此做個(gè)記錄芥映。

二、漸進(jìn)式 Web 應(yīng)用(PWA)

PWA全稱 Progressive Web App缝裤,即漸進(jìn)式Web應(yīng)用屏轰,實(shí)際上就是一個(gè)網(wǎng)頁(yè)應(yīng)用,加上App Manifest 和 ServiceWorker 來(lái)實(shí)現(xiàn) PWA 的安裝和離線訪問(wèn)等功能憋飞,使得Web應(yīng)用接近原生 APP霎苗。

  • 可以添加到主屏幕,點(diǎn)擊主屏幕圖標(biāo)可以實(shí)現(xiàn)啟動(dòng)動(dòng)畫以及隱藏地址欄榛做;
  • 實(shí)現(xiàn)離線緩存功能唁盏,即使客戶端沒(méi)有網(wǎng)絡(luò),依然可以正常訪問(wèn)检眯;
  • 實(shí)現(xiàn)消息推送等等……

我們這里主要使用 Service Worker 實(shí)現(xiàn)離線緩存厘擂,減少網(wǎng)絡(luò)通信,提高頁(yè)面刷新效率锰瘸。

三刽严、ServiceWorker

ServiceWorker 是 Chrome 團(tuán)隊(duì)提出并力推的一個(gè) Web API,用于給 Web 應(yīng)用提供高級(jí)的可持續(xù)的后臺(tái)處理能力避凝。

在這里插入圖片描述

它本質(zhì)上充當(dāng)服務(wù)器和瀏覽器之間的代理服務(wù)器舞萄,能夠攔截網(wǎng)站的請(qǐng)求,從而控制頁(yè)面加載管削。

在 Service Worker 中我們可以做很多事情倒脓,比如攔截客戶端的請(qǐng)求、向客戶端發(fā)送消息含思、向服務(wù)器發(fā)起請(qǐng)求等等崎弃,其中最重要的作用之一就是離線資源緩存。

由于其攔截請(qǐng)求的特性含潘,出于安全考慮饲做,Service Worker 只能被使用在 https 或者本地的 localhost 環(huán)境下

關(guān)于 Service Worker 在不同瀏覽器的兼容性调鬓,詳見(jiàn) caniuse 中提供的信息:

在這里插入圖片描述

可以看到 IE 和 Opera Mini 的全版本都不支持艇炎,但主流瀏覽器:Edge、Chrome腾窝、Firefox缀踪、Safari 較新的版本都是支持的居砖,可以放心用,不過(guò)建議在用之前還是得先做好評(píng)估驴娃。

四奏候、ServiceWorker啟動(dòng)過(guò)程

當(dāng)用戶首次導(dǎo)航至 URL 時(shí),服務(wù)器會(huì)返回響應(yīng)的網(wǎng)頁(yè)唇敞。

  1. 調(diào)用 register() 函數(shù)時(shí)蔗草, Service Worker 開(kāi)始下載。
  2. 在注冊(cè)過(guò)程中疆柔,瀏覽器會(huì)下載咒精、解析并執(zhí)行 ServiceWorker()。如果在此步驟中出現(xiàn)任何錯(cuò)誤旷档,register() 返回的 promise 都會(huì)執(zhí)行 reject 操作模叙,并且 Service Worker 會(huì)被廢棄。
  3. 一旦 ServiceWorker 成功執(zhí)行了鞋屈,install 事件就會(huì)激活范咨。
  4. 安裝完成,ServiceWorker 便會(huì)激活厂庇,并控制在其范圍內(nèi)的一切渠啊。如果生命周期中的所有事件都成功了,ServiceWorker 便已準(zhǔn)備就緒权旷,隨時(shí)可以使用了替蛉。
在這里插入圖片描述

在 ServiceWorker 的啟動(dòng)過(guò)程中,若有任何環(huán)節(jié)出錯(cuò)拄氯,則 ServiceWorker 會(huì)被直接廢棄灭返,直到下次刷新頁(yè)面,將重新啟動(dòng)坤邪。

五、實(shí)現(xiàn)ServiceWorker

5.1 注冊(cè)

如果當(dāng)前使用的瀏覽器支持 ServiceWorker 罚缕,在 window.navigator 下則會(huì)存在 serviceWorker 對(duì)象艇纺,我們可以使用這個(gè)對(duì)象的 register 方法來(lái)注冊(cè)一個(gè) ServiceWorker。

備注:ServiceWorker在使用的過(guò)程中存在大量的 Promise 邮弹,對(duì)于 Promise 不是很了解的話可以先去看一下相關(guān)文檔黔衡。ServiceWorker 的注冊(cè)方法返回的也是一個(gè) Promise 。

/* index.html or index.js */
/* 判斷當(dāng)前瀏覽器是否支持serviceWorker */
if ('serviceWorker' in navigator) {
    /* 當(dāng)頁(yè)面加載完成就創(chuàng)建一個(gè)serviceWorker */
    window.addEventListener('load', function () {
        /* register 方法接受兩個(gè)參數(shù) */
        /* 參數(shù)一:指定serviceWorker文件路徑  */
        /* 參數(shù)二:scope參數(shù)是可選的腌乡,可以用來(lái)指定你想讓serviceWorker控制的內(nèi)容子目錄 */
        /* 在這個(gè)例子里盟劫,我們指定了'/',表示根網(wǎng)域下的所有內(nèi)容与纽。這也是默認(rèn)值侣签。 */
        navigator.serviceWorker.register('./service-worker.js', {scope: './'})
            .then(function (registration) {
                 console.log('ServiceWorker registration successful with scope: ', registration.scope);
             })
            .catch(function (err) {
                console.log('ServiceWorker registration failed: ', err);
             });
    });
}

register 方法返回一個(gè) Promise 塘装。如果注冊(cè)失敗,可以通過(guò) catch 來(lái)捕獲錯(cuò)誤信息影所;如果注冊(cè)成功蹦肴,可以使用 then 來(lái)獲取一個(gè) ServiceWorkerRegistration 的實(shí)例。

5.2 安裝

注冊(cè)完 ServiceWorker 之后猴娩,瀏覽器會(huì)為我們自動(dòng)安裝它阴幌,因此我們就可以在 register 時(shí)指定的 service-worker.js 文件中編寫對(duì)應(yīng)的安裝及攔截邏輯,監(jiān)聽(tīng)它的 install 事件卷中。

/* service-worker.js */
this.addEventListener('install', function (event) {
  console.log('Service Worker install');
});

類似的矛双,ServiceWorker 在安裝完成后會(huì)被激活,所以我們也可監(jiān)聽(tīng) activate 事件蟆豫。

/* service-worker.js */
this.addEventListener('activate', function (event) {
  console.log('Service Worker activate');
});

這時(shí)议忽,我們可以在瀏覽器開(kāi)發(fā)者工具的”應(yīng)用程序“欄目中看到我們注冊(cè)的 ServiceWorker。


在這里插入圖片描述

在默認(rèn)情況下无埃,ServiceWorker 必定會(huì)每24小時(shí)被下載一次徙瓶,如果下載的文件是最新文件,那么它就會(huì)被重新注冊(cè)和安裝嫉称,但不會(huì)被激活侦镇,當(dāng)不再有頁(yè)面使用舊的 ServiceWorker 的時(shí)候,它就會(huì)被激活织阅。

備注:由于以上特性不方便開(kāi)發(fā)壳繁,因此這里勾引選了"重新加載時(shí)更新"的選項(xiàng),勾選后每次刷新頁(yè)面都能使用最新的 ServiceWorker 文件荔棉。

此處編寫一個(gè)最簡(jiǎn)單的緩存 index.html 的例子闹炉,代碼如下:

/* service-worker.js */
/* 監(jiān)聽(tīng)安裝事件,install事件一般是被用來(lái)設(shè)置瀏覽器的離線緩存邏輯 */
this.addEventListener('install', function (event) {
    /* 通過(guò)這個(gè)方法可以防止緩存未完成润樱,就關(guān)閉serviceWorker */
    event.waitUntil(
        /* 創(chuàng)建一個(gè)名叫V1的緩存版本 */
        caches.open('v1').then(function (cache) {
            /* 指定要緩存的內(nèi)容渣触,地址為相對(duì)于跟域名的訪問(wèn)路徑 */
            return cache.addAll([
                './index.html'
            ]);
        })
    );
});

/* 注冊(cè)fetch事件,攔截全站的請(qǐng)求 */
this.addEventListener('fetch', function(event) {
  event.respondWith(
      /* magic goes here */
      ......
      /* 在緩存中匹配對(duì)應(yīng)請(qǐng)求資源直接返回 */
    caches.match(event.request)
  );
});

六壹若,借助VuePess的插件實(shí)現(xiàn)ServiceWorker

VuePress 官方提供了對(duì)PWA的支持嗅钻,安裝 plugin-pwa 插件后,在 config.js 中進(jìn)行以下配置即可:

module.exports = {
  /* 在HTML<head>標(biāo)簽中插入PWA配置文件 */
  head: [
    ['link', { rel: 'manifest', href: '/manifest.json' }]
    ……
  ], 
  ……
  plugins: [
      '@vuepress/pwa', {      /* 啟用PWA插件店展,實(shí)現(xiàn)ServiceWorker緩存機(jī)制 */
          serviceWorker: true,/* VuePress將自動(dòng)生成并注冊(cè)一個(gè)ServiceWorker */
          updatePopup: true   /* 監(jiān)聽(tīng)服務(wù)端內(nèi)容养篓,發(fā)生更新時(shí)提供refersh按鈕刷新頁(yè)面 */
        },
    ]
}

配置時(shí)需要提供 Manifest 和 icons,具體詳見(jiàn):Web app manifests赂蕴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柳弄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子概说,更是在濱河造成了極大的恐慌碧注,老刑警劉巖嚣伐,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異应闯,居然都是意外死亡纤控,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門碉纺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)船万,“玉大人,你說(shuō)我怎么就攤上這事骨田」⒌迹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵态贤,是天一觀的道長(zhǎng)舱呻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)悠汽,這世上最難降的妖魔是什么箱吕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮柿冲,結(jié)果婚禮上茬高,老公的妹妹穿的比我還像新娘。我一直安慰自己假抄,他們只是感情好怎栽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著宿饱,像睡著了一般熏瞄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谬以,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天强饮,我揣著相機(jī)與錄音,去河邊找鬼为黎。 笑死胡陪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碍舍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼邑雅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼片橡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淮野,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捧书,失蹤者是張志新(化名)和其女友劉穎吹泡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體经瓷,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爆哑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舆吮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揭朝。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖色冀,靈堂內(nèi)的尸體忽然破棺而出潭袱,到底是詐尸還是另有隱情,我是刑警寧澤锋恬,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布屯换,位于F島的核電站,受9級(jí)特大地震影響与学,放射性物質(zhì)發(fā)生泄漏彤悔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一索守、第九天 我趴在偏房一處隱蔽的房頂上張望晕窑。 院中可真熱鬧,春花似錦蕾盯、人聲如沸幕屹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)望拖。三九已至,卻和暖如春挫鸽,著一層夾襖步出監(jiān)牢的瞬間说敏,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工丢郊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盔沫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓枫匾,卻偏偏與公主長(zhǎng)得像架诞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子干茉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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