Google_PWA_ServiceWork_漸進式 Web 應用_給應用提供離線體驗

来源:https://www.cnblogs.com/lxhbky/archive/2019/08/01/11284753.html
-Advertisement-
Play Games

前言:今天結識了google PWA提供的一個對移動端Web應用提供離線體驗的一個功能,感覺很有用。我這裡不分享自己的寫法和代碼。官網文檔說的很詳細,直接粘過來大家看吧。 推薦官網地址:你的第一個漸進式 Web 應用(Progressive Web App - PWA) 文章詳情如下: 簡介 什麼是 ...


  前言:今天結識了google PWA提供的一個對移動端Web應用提供離線體驗的一個功能,感覺很有用。我這裡不分享自己的寫法和代碼。官網文檔說的很詳細,直接粘過來大家看吧。

  推薦官網地址:你的第一個漸進式 Web 應用(Progressive Web App - PWA)

 

 

文章詳情如下:

 

簡介

什麼是 Web 應用,一個漸進式 Web 應用?

漸進式 Web 應用會在桌面和移動設備上提供可安裝的、仿應用的體驗,可直接通過 Web 進行構建和交付。它們是快速、可靠的 Web 應用。最重要的是,它們是適用於任何瀏覽器的 Web 應用。如果你在構建一個 Web 應用,其實已經開始構建漸進式 Web 應用了。

快速 & 可靠

每個 Web 體驗都必須快速,對於漸進式 Web 應用更是如此。快速是指在屏幕上獲取有意義內容所需的時間,要在不到 5 秒的時間內提供互動式體驗。

並且,它必須真的很快。很難形容可靠的高性能有多重要。可以這樣想: 本機應用的首次載入令人沮喪。應用商店和漫長的下載都是門檻,不過,該前期成本包含了今後該應用的每次啟動時間,一旦你安裝好該應用,這些啟動過程就不會再有額外的延遲。每個應用的啟動速度都與上一次一樣快,沒有任何差異。已安裝的漸進式 Web 應用必須能讓用戶獲得可靠的性能。

安裝

漸進式 Web 應用可以在瀏覽器選項卡中運行,但也可以安裝。為網站添加書簽只是添加了一個快捷方式,但已安裝的漸進式 Web 應用的外觀和行為會與任何已安裝的應用類似。它與其它應用的啟動位置是一樣的。你可以控制啟動體驗,包括自定義啟動畫面、圖標等。它在應用視窗中作為應用運行,沒有地址欄或其它瀏覽器 UI。與其它已安裝的應用一樣,它是任務管理器中的頂級應用。

請記住,讓可安裝的 PWA 保持快速可靠是至關重要的。安裝 PWA 的用戶希望他們的應用正常運行,無論他們使用何種網路連接。這是每個已安裝應用必須滿足的基線預期。

手機 & 桌面

使用響應式設計技術,漸進式 Web 應用可在移動桌面上工作,使用跨平臺的單一代碼庫。如果你正在考慮是否編寫本機應用,請看看 PWA 提供的好處。

你將構建什麼

在此 codelab 中,你將使用漸進式 Web 應用技術構建天氣 Web 應用。你的應用將:

  • 使用響應式設計,因此它可用在桌面或移動設備上。
  • 快速,使用 Service Worker 來預緩存運行時所需的應用資源(HTML,CSS,JavaScript,圖像),併在運行時緩存天氣數據以提高性能。
  • 可安裝,使用 Web 應用清單(manifest)和 beforeinstallprompt 事件告訴用戶它是可安裝的。
  •  

    95fe6f7fbeee5bb1.png

Warning:為了簡化此 codelab ,並解釋提供離線體驗的基礎知識,我們使用的是原生 JavaScript。在生產應用中,我們強烈建議使用 Workbox 工具來構建 Service Worker 。它可以幫你消除許多可能遇到的坑和死角。

你將學到什麼

  • 如何創建和添加 Web 應用清單
  • 如何提供簡單的離線體驗
  • 如何提供完整的離線體驗
  • 如何使你的應用可安裝

此 codelab 專註於漸進式 Web 應用。屏蔽了不相關的概念和代碼塊,併為你提供簡單的複製和粘貼。

你需要什麼

  • 最近版本的 Chrome(74 或更高版本)

    PWA 只是個 Web 應用,因此適用於所有瀏覽器,但我們將使用 Chrome DevTools 的一些功能來更好地瞭解瀏覽器層面的情況,並用它來測試安裝體驗。

  • 瞭解 HTML,CSS,JavaScript 和Chrome DevTools 。

環境準備

獲取 Dark Sky API 的密鑰

我們的天氣數據來自 Dark Sky API。要使用它,你需要申請 API 密鑰。它很容易使用,並且可以免費用於非商業項目。

註冊一個 API Key

Note: 你還可以在沒有 Dark Sky API 密鑰的情況下完成此 codelab。如果我們的伺服器無法從 Dark Sky API 獲取真實數據,它將返回假數據。

驗證你的 API 密鑰是否正常工作

要測試你的 API 密鑰是否正常工作,請向 DarkSky API 發出 HTTP 請求。修改以下網址,將 DARKSKY_API_KEY 替換為你的 API 密鑰。如果一切正常,你應該看到紐約市的最新天氣預報。

https://api.darksky.net/forecast/DARKSKY_API_KEY/40.7720232,-73.9732319

獲取代碼

我們已將此項目所需的一切都放入 Git 倉庫中。首先,你需要獲取代碼併在你喜歡的開發環境中打開它。對於此代碼庫,我們建議使用 Glitch。

強烈推薦: 使用 Glitch 導入倉庫

推薦用 Glitch 來使用此代碼庫。

  1. 打開一個新的瀏覽器選項卡,然後轉到 https://glitch.com 。
  2. 如果你沒有帳戶,則需要註冊。
  3. 單擊 New Project,然後單擊 Clone from Git Repo.
  4. 克隆 https://github.com/googlecodelabs/your-first-pwapp.git 並單擊確定。
  5. 獲取完 repo 後,編輯 .env 文件,並使用 DarkSky API 密鑰來更新它。
  6. 單擊 Show Live 按鈕以查看此 PWA 的運行情況。

替代方案: 下載代碼併在本地工作

如果你想下載代碼併在本地工作,你需要安裝好最新版本的 Node 和代碼編輯器。

Caution: 如果你在本地工作,某些 Lighthouse 審計可能無法通過,甚至可能無法安裝,因為本地伺服器並沒有在安全環境下運行。

下載源碼

  1. 解壓縮下載的 zip 文件。
  2. 運行 npm install 以安裝運行伺服器所需的依賴項。
  3. 編輯 server.js 並設置 DarkSky API 密鑰。
  4. 運行 node server.js 以在埠 8000 上啟動伺服器.
  5. 打開瀏覽器選項卡並轉到 http://localhost:8000

建立基線

我們的起點是什麼?

我們的起點是為此 codelab 設計的基本天氣應用。代碼已經大幅簡化,以突顯此代碼庫中的概念,並且它幾乎沒有做錯誤處理。如果你選擇在生產應用中復用此代碼,請確保處理各種錯誤並完全測試所有代碼。

我們將試著......

  1. 使用右下角的藍色加號按鈕來添加新城市。
  2. 使用右上角的刷新按鈕來刷新數據。
  3. 使用每張城市卡片右上角的 x 來刪除城市。
  4. 瞭解它在桌面和移動設備上的工作原理。
  5. 看看當離線時會發生什麼。
  6. 使用 Chrome 的“網路”面板,查看當網路受限製為慢速3G 時會發生什麼。
  7. 通過更改 server.js 中的 FORECAST_DELAY 為天氣預報伺服器添加延遲

用 Lighthouse 進行審計

Lighthouse是一款易於使用的工具,可幫助你提高網站和網頁的質量。它可用來對性能,可訪問性,漸進式 Web 應用等進行審計。每種審計及都有一個參考文檔,解釋了該審計為何重要,以及如何解決所發現的問題。

 

 

我們將使用 Lighthouse 來審計我們的天氣應用,並驗證我們所做的更改。

Note: 你可以在 Chrome DevTools 中,以命令行或 Node 模塊的方式運行 Lighthouse。考慮將Lighthouse 添加到你的構建流程中,以確保你的 Web 應用不會出現回歸問題。

讓我們運行 Lighthouse

  1. 在新選項卡中打開項目。
  2. 打開 Chrome DevTools 並切換到 Audits 選項卡,DevTools 會顯示審計類別列表,全部啟用它們。
  3. 單擊 Run audits,60-90 秒後,Lighthouse 會在頁面上顯示報告。

審計漸進式 Web 應用

我們將重點關註漸進式 Web 應用的審計結果。

af1a64a13725428e.png

這裡有很多紅色信息需要關註:

  • ❗失敗: 在離線時當前頁面未給出 200 響應。
  • ❗失敗: 在離線時 start_url 未給出 200 響應。
  • ❗失敗: 未註冊用來控制頁面和 start_url 的 Service Worker。
  • ❗失敗: Web 應用清單 (manifest) 不符合可安裝性要求。
  • ❗失敗: 未配置自定義閃屏。
  • ❗失敗: 未設置地址欄的主題顏色。

讓我們進入並開始修複其中的一些問題!

添加 Web 應用清單

到本節結束時,我們的天氣應用將通過以下審計:

  • Web 應用清單 (manifest) 不符合可安裝性要求。
  • 未配置自定義的初始屏幕。
  • 未設置地址欄的主題顏色。

創建 Web 應用清單

Web 應用清單是一個簡單的 JSON 文件,它使開發人員能夠控制本應用對用戶的顯示方式。

使用 Web 應用清單,你的 Web 應用可以:

  • 告訴瀏覽器你希望本應用在獨立視窗中打開( display )。
  • 定義首次啟動本應用時要打開哪個頁面( start_url )。
  • 定義應用在 Dock 或應用啟動器上應該是什麼樣子( short_name ,icons )。
  • 創建一個閃屏( name , icons , colors )。
  • 告訴瀏覽器以橫向或縱向模式打開視窗( orientation )。
  • 以及很多其它配置 。

在項目中創建名為 public/manifest.json 的文件,並複製/粘貼以下內容:

public/manifest.json

 
{
  "name": "Weather",
  "short_name": "Weather",
  "icons": [{
    "src": "/images/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    }, {
      "src": "/images/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    }, {
      "src": "/images/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    }, {
      "src": "/images/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "/images/icons/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    }, {
      "src": "/images/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }],
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#3E4EB8",
  "theme_color": "#2F3BA2"
}

本清單可支持一組用於不同屏幕尺寸的圖標。對於此 codelab ,我們還包含了一些其它的,因為我們需要把它們集成進 iOS。

Note: 如果想安裝它,Chrome 會要求你至少提供 192x192px 圖標和 512x512px 圖標。但是你也可以提供其它尺寸。 Chrome 會使用最接近 48dp 的圖標,例如,2x 設備上的 96px 或 3x 設備的 144px。

添加指向 Web 應用清單的鏈接

接下來,我們需要通過嚮應用中的每個頁面添加 <link rel="manifest"... 來把此清單告知瀏覽器。把下列代碼行添加到 index.html 文件中的 <head> 元素下。

public/index.html

 
<!-- CODELAB: Add link rel manifest -->
<link rel="manifest" href="/manifest.json">

DevTools Detour

DevTools 提供了一種快速簡便的方法來檢查你的 manifest.json 文件。打開 Application 面板上的 Manifest 窗格。如果你已正確添加清單信息,你將能夠在此窗格中看到它以對人類友好的格式進行解析和顯示。

 

添加 iOS 元標記和圖標

iOS 上的 Safari 不支持 Web 應用清單( 至少目前為止 ),因此你需要將傳統的 meta 標簽添加到 index.html 文件的 <head> 中:

public/index.html

 
<!-- CODELAB: Add iOS meta tags and icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Weather PWA">
<link rel="apple-touch-icon" href="/images/icons/icon-152x152.png">

額外工作: 簡易 Lighthouse 修複

我們的 Lighthouse 審計還提出了一些其它很容易解決的問題,所以讓我們先來處理下這些問題。

設置元描述

根據 SEO 審計,Lighthouse 提出我們的 “ Document does not have a meta description. ”。描述可以顯示在 Google 的搜索結果中。高質量,獨特的描述可以使你的搜索結果與搜索用戶更相關,並可以增加搜索流量。

要添加描述,請將以下 meta 標記添加到文檔的 <head> 中:

public/index.html

 
<!-- CODELAB: Add description here -->
<meta name="description" content="A sample weather app">

設置地址欄的主題顏色

在 PWA 審計中,Lighthouse 提出我們的應用“ Does not set an address-bar theme color ”。將瀏覽器的地址欄設置為與你的品牌色相匹配,可以提供更加沉浸式的用戶體驗。

要在移動設備上設置主題顏色,請將以下 meta 標記添加到文檔的 <head> 中:

public/index.html

 
<!-- CODELAB: Add meta theme-color -->
<meta name="theme-color" content="#2F3BA2" />

用 Lighthouse 驗證更改

再次運行 Lighthouse(通過單擊“審計”窗格左上角的+號)並驗證你的更改。

SEO 審計

*✅通過: 文檔已有元描述。

漸進式應用審計

  • ❗失敗: 在離線時當前頁面未給出 200 響應。
  • ❗失敗: 在離線時 start_url 未給出 200 響應。
  • ❗失敗: 未註冊用來控制頁面和 start_url 的 Service Worker。 *✅通過: Web 應用清單符合可安裝性要求。 *✅通過: 已配置自定義閃屏。 *✅通過: 已設置地址欄的主題顏色。

提供基本的離線體驗

用戶會期待所安裝的應用在離線時始終具有基線體驗。因此對於可安裝的 Web 應用來說,永遠不會顯示 Chrome 的離線恐龍圖是至關重要的。離線體驗的範圍包括簡單的離線頁面、具有先前緩存數據的只讀體驗,甚至具有完全功能的離線體驗(在網路連接恢復時自動同步)。

在本節中,我們將向天氣應用添加一個簡單的離線頁面。如果用戶在離線時嘗試載入應用,則會顯示我們的自定義頁面,而不是瀏覽器顯示的典型離線頁面。到本節結束時,我們的天氣應用將通過以下審計:

  • 在離線時當前頁面未給出 200 響應。
  • 在離線時 start_url 未給出 200 響應。
  • 未註冊用來控制頁面和 start_url 的 Service Worker。

在下一部分中,我們將使用完整的離線體驗替換我們的自定義離線頁面。這將改善離線體驗,但更重要的是,它將顯著提高我們的性能,因為我們的大多數資產(HTML,CSS 和 JavaScript)都將在本地存儲和提供,從而消除了網路方面的潛在瓶頸。

向 Service worker 求援

如果你對 Service Worker 不熟悉,可以通過閱讀 Service Workers 簡介來瞭解它們可以做什麼,它們的生命周期如何工作等等,從而獲得初步的理解。完成此 codelab 後,請務必查看 Debugging Service Workers code lab以便更深入地瞭解如何與 Service Worker 合作。

通過 Service Worker 提供的功能應被視為漸進增強功能,並且僅在瀏覽器支持時才添加。例如,對於 Service Worker ,你可以為應用緩存應用外殼和數據,以便在網路不可用時也能使用它。如果不支持 Service Worker ,則不會調用離線代碼,而用戶將獲得基本體驗。使用特性檢測來提供漸進增強功能的開銷很小,並且在不支持該功能的舊瀏覽器中不會出錯。

Warning: Service Worker 功能僅在通過 HTTPS 訪問的頁面上可用(http://localhost 及其等價物也可用來協助我們進行測試)。

註冊 Service Worker

第一步是註冊 Service Worker 。將以下代碼添加到 index.html 文件中:

public/index.html

 
// CODELAB: Register service worker.
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
        .then((reg) => {
          console.log('Service worker registered.', reg);
        });
  });
}

此代碼檢查 Service Worker API 是否可用,如果是,則在頁面載入完畢時註冊 /service-worker.js 的 Service Worker。

註意, Service Worker 是從根目錄提供的,而不是從 /scripts/ 目錄。這是設置 Service Worker 的 scope 的最簡單方法。Service Worker 的 scope 會決定 Service Worker 能控制哪些文件,換句話說, Service Worker 將攔截哪個路徑下的請求。預設的 scope 是 Service Worker 文件所在的位置並及其各級目錄。因此,如果 service-worker.js 位於根目錄中,則 Service Worker 將控制對該域中所有網頁的請求。

Precache 離線頁面

首先,我們需要告訴 Service Worker 緩存什麼。我們已經創建了一個簡單的離線頁面 ( public/offline.html ),只要沒有網路連接,我們就會顯示它。

在 service-worker.js 中,將 '/offline.html', 添加到 FILES_TO_CACHE 數組中,最終結果應如下所示:

public/service-worker.js

 
// CODELAB: Update cache names any time any of the cached files change.
const FILES_TO_CACHE = [
  '/offline.html',
];

接下來,我們需要修改 install 事件以告知 Service Worker 預先緩存離線頁面:

public/service-worker.js

 
// CODELAB: Precache static resources here.
evt.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('[ServiceWorker] Pre-caching offline page');
      return cache.addAll(FILES_TO_CACHE);
    })
);

Note: Service Worker 的事件和生命周期將在下一節中介紹。

我們的 install 事件現在使用 caches.open() 打開緩存並傳入緩存名稱。提供緩存名稱能讓我們對緩存資源進行版本控制或移除,這樣我們我們就能輕鬆的修改一個而不影響另一個。

一旦緩存打開,我們就可以調用 cache.addAll() 了,它接受一個 URL 列表,從伺服器獲取這些 URL 並將其響應添加到緩存中。請註意,如果任何單個請求失敗,cache.addAll() 就不會生效。這意味著你可以確保,如果安裝步驟成功了,你的緩存必然處於一致的狀態。但是,如果由於某種原因而失敗了,它將在下次 Service Worker 啟動時自動重試。

DevTools Detour

讓我們來看看如何使用 DevTools 來理解和調試 Service Worker 。在重新載入頁面之前,打開 DevTools,轉到 Application面板上的 Service Workers 窗格。它應該如下所示:

 

當你看到這樣的空白頁面時,表示當前打開的頁面中沒有任何已註冊的 Service Worker 。

現在,重新載入頁面,“Service Worker” 窗格應如下所示:

69808e4bf3aee41b.png

當你看到這樣的信息時,表示該頁面正在運行 Service Worker 。

狀態標簽旁邊有一個數字(這裡是34251),在你使用 Service Worker 時,請密切註意該數字。這是一種判斷你的 Service Worker 是否已更新的簡單方式。

清理舊的離線頁面

我們將使用 activate 事件來清理緩存中的任何舊數據。此代碼可確保你的 Service Worker 在任何應用外殼文件發生更改時更新其緩存。為了使其工作,你需要在 Service Worker 文件的頂部增加 CACHE_NAME 變數。

將以下代碼添加到 activate 事件中:

public/service-worker.js

 
// CODELAB: Remove previous cached data from disk.
evt.waitUntil(
    caches.keys().then((keyList) => {
      return Promise.all(keyList.map((key) => {
        if (key !== CACHE_NAME) {
          console.log('[ServiceWorker] Removing old cache', key);
          return caches.delete(key);
        }
      }));
    })
);

DevTools Detour

打開 “Service Worker” 窗格,刷新頁面,你將看到安裝了新的 Service Worker ,並且狀態編號會遞增。

1db827d76bc0b359.png

更新後的 Service Worker 立即獲得控制權,因為我們的 install 事件以 self.skipWaiting() 結束, activate 事件以 self.clients.claim() 結束。如果沒有這些,只要有一個打開著此頁面的選項卡,舊的 Service Worker 就會繼續控制此頁面。

處理失敗的網路請求

最後,我們需要處理 fetch 事件。我們將使用 "網路優先,回退到緩存" 的策略 。 Service Worker 將首先嘗試從網路獲取資源,如果失敗,它將從緩存中返回離線頁面。

6302ad4ba8460944.png

public/service-worker.js

 
// CODELAB: Add fetch event handler here.
if (evt.request.mode !== 'navigate') {
  // Not a page navigation, bail.
  return;
}
evt.respondWith(
    fetch(evt.request)
        .catch(() => {
          return caches.open(CACHE_NAME)
              .then((cache) => {
                return cache.match('offline.html');
              });
        })
);

fetch 處理程式只需要處理頁面導航,其它請求會被該處理程式忽略,交由瀏覽器進行常規處理。但是,如果該請求的 .mode 是 navigate ,就會嘗試用 fetch 從網路獲取項目。如果失敗,則 catch 處理程式就會用 caches.open(CACHE_NAME) 打開緩存,並使用 cache.match('offline.html') 來獲得預緩存的離線頁面。然後使用 evt.respondWith() 將結果傳回瀏覽器。

Key Point: 把 fetch 調用包裝在 evt.respondWith() 中會阻止瀏覽器的預設處理,並告訴瀏覽器我們要自己處理該響應。如果你沒有在 fetch 處理程式中調用 evt.respondWith() ,你只會獲得預設的網路行為。

DevTools Detour

讓我們檢查一下,確保一切正常。打開 “Service Worker” 窗格,刷新頁面,你將看到安裝了新的 Service Worker ,並且狀態編號會增加。

我們還可以查看已緩存的內容。轉到 DevTools 的 Application 面板上的 Cache Storage 窗格。右鍵單擊 Cache Storage,選擇 Refresh Caches,展開該部分,你應該會在左側看到靜態緩存的名稱。單擊緩存名稱將顯示緩存的所有文件。

c80a2a2e93c1c3ee.png

現在,我們來測試下離線模式。返回 DevTools 的 Service Workers 窗格並檢查 Offline 覆選框。檢查後,你應該會在 Network 面板選項卡旁邊看到一個黃色警告圖標。這表示你處於離線狀態。

984b34dc2aa667a.png

重新載入你的頁面......可以了!我們得到我們的離線熊貓圖,而不是 Chrome 的離線恐龍圖!

測試 Service Worker 的小技巧

當涉及緩存時,調試 Service Worker 可能是一個挑戰,如果緩存未按預期更新,事情可能變成噩夢。在典型的 Service Worker 生命周期和代碼中的錯誤中,你可能會很快感到沮喪。但是,不必如此。

使用 DevTools

在 “Application” 面板的“ Service Worker ”窗格中,有一些覆選框可以讓你更輕鬆。

 

  • Offline - 選中後會模擬離線體驗並阻止任何請求進入網路。
  • Update on reload - 選中後將獲得最新的 Service Worker ,安裝它,並立即激活它。
  • Bypass for network - 當檢查請求時,繞過 Service Worker 並直接發送到網路。

來點新鮮的

在某些情況下,你可能會發現自己正在載入已緩存的數據或者沒能按預期更新內容。要清除所有已保存的數據(localStorage,indexedDB 數據,緩存文件)並刪除任何 Service Worker ,請使用 “Application” 選項卡中的 “Clear storage” 窗格。或者,你也可以使用隱身視窗。

 

其它提示:

  • 當 Service Worker 取消註冊之後,它可能仍然會列在這裡,直到包含它的瀏覽器視窗關閉。
  • 如果你的應用打開了多個視窗,則直到將所有視窗都重新載入並更新到最新的 Service Worker 之前,新的 Service Worker 不會生效。
  • 取消註冊 Service Worker 不會清除緩存!
  • 如果存在 Service Worker 並且註冊了新的 Service Worker ,則除非你立即獲得控制權 ,否則在重新載入頁面之前,新的 Service Worker 將不會獲得控制權。

使用 Lighthouse 驗證這些更改

再次運行 Lighthouse 並驗證你的更改。在驗證更改之前,請不要忘記取消 “Offline” 覆選框!

SEO 審計

*✅通過: 文檔已有元描述。

漸進式應用審計

*✅通過: 在離線時當前頁面未給出 200 響應。 *✅通過: 在離線時 start_url 未給出 200 響應。 *✅通過: 未註冊用來控制頁面和 start_url 的 Service Worker。 *✅通過: Web 應用清單符合可安裝性要求。 *✅通過: 已配置自定義閃屏。 *✅通過: 已設置地址欄的主題顏色。

提供完整的離線體驗

將手機開啟飛行模式,然後嘗試運行一些你喜歡的應用。幾乎在所有情況下,它們都提供了相當強大的離線體驗。用戶希望他們的應用具有穩健的體驗,Web 應用也不例外。漸進式 Web 應用在設計時應該把離線作為核心場景。

Key Point:離線優先的設計可以通過減少應用發出的網路請求數量並改用預先緩存資源並直接從本地緩存提供資源來大幅提高Web 應用的性能。即使用最快的網路連接,從本地緩存提供的服務也仍然會更快!

Service Worker 生命周期

Service Worker 的生命周期是最複雜的部分。如果你不知道它想要做什麼以及有什麼好處,你可能會覺得它處處和你作對。但是一旦你知道它是如何工作的,你就可以為用戶提供無縫、免打擾的更新,將網路應用和本機應用中最好的一面結合起來。

Key Point:此 codelab 僅涵蓋 Service Worker 生命周期的基礎知識。要深入瞭解,請參閱有關 WebFundamentals 的 Service Worker 生命周期 文檔。

install 事件

Service Worker 獲得的第一個事件是 install 。它會在 Service Worker 執行時立即觸發,並且每個 Service Worker 只會調用一次。如果你更改了 Service Worker 腳本,瀏覽器就會將其視為另一個 Service Worker,並且它將獲得自己的 install 事件。

 

通常, install 事件用於緩存應用運行時所需的全部內容。

activate 事件

Service Worker 每次啟動時都會收到 activate 事件。 activate 事件的主要目的是配置 Service Worker 的行為,清除以前運行中遺留的任何資源(例如舊緩存),並讓 Service Worker 準備好處理網路請求(例如下麵要講的 fetch 事件)。

fetch 事件

fetch 事件允許 Service Worker 攔截並處理任何網路請求。它可以通過網路獲取資源、可以從自己的緩存中提取資源、生成自定義響應,以及很多種不同的選擇。查看離線寶典瞭解你可以使用的不同策略。

更新 Service Worker

瀏覽器會檢查每個頁面載入時是否有新版本的 Service Worker 。如果找到新版本,則會下載這個新版本併在後臺安裝,但不會激活它。它會處於等待狀態,直到不再打開任何使用舊 Service Worker 的頁面。一旦關閉了使用舊 Service Worker 的所有視窗,新的 Service Worker 就會被激活並獲得控制權。更多詳細信息,請參閱 Service Worker 生命周期文檔中的更新 Service Worker部分。

選擇正確的緩存策略

選擇正確的緩存策略取決於你嘗試緩存的資源類型以及以後可能需要的資源。對於這個天氣應用,需要緩存的資源可以分為兩類: 需要預先緩存的資源以及將在運行時緩存的數據。

緩存靜態資源

預先緩存資源與用戶安裝桌面或移動應用時的情況類似。應用運行所需的關鍵資源已安裝或緩存在設備上,以後無論是否有網路連接都可以載入它們。

對於這個應用,我們將在安裝 Service Worker 時預先緩存所有靜態資源,以便把我們運行應用所需的一切都存儲在用戶的設備上。為了確保我們的應用快速載入,我們將使用緩存優先策略:不去網路獲取資源,而是從本地緩存中取出;只有當緩存不可用時,我們才會嘗試從網路中獲取它。

44860840e2090bd8.png

從本地緩存中取可消除任何網路方面的變數。無論用戶使用何種網路(WiFi,5G,3G 甚至 2G),我們需要運行的關鍵資源都幾乎可以立即使用。

Caution: 在此示例中,使用 cache-first 策略提供靜態資源,這會導致在不詢問網路的情況下返回任何緩存內容的副本。雖然 cache-first 策略易於實施,但它可能會在將來的演化中帶來挑戰。

緩存應用數據

stale-while-revalidate strategy 對某些類型的數據是理想的,比如本應用。它會儘可能快地獲取屏幕上要顯示的數據,然後在網路返回最新數據後進行更新。 Stale-while-revalidate 意味著我們需要發起兩個非同步請求,一個到緩存,一個到網路。

6ebb2681eb1f58cb.png

在正常情況下,緩存數據幾乎會立即返回,為應用提供可以使用的最新數據。然後,當網路請求返回時,將使用來自網路的最新數據更新應用。

對於我們的應用,這提供了比 "網路優先,回退到緩存" 策略更好的體驗,因為用戶不必等到網路請求超時後才在屏幕上看到某些內容。他們最初可能會看到較舊的數據,但一旦網路請求返回,應用就將使用最新數據進行更新。

更新應用邏輯

如前所述,應用需要啟動兩個非同步請求,一個到緩存,一個到網路。該應用使用 window 上的 caches 對象來訪問緩存並獲取最新數據。這是漸進增強的一個很好的例子,因為 caches 對象可能並非在所有瀏覽器中都可用,如果不可用,網路請求仍然可以工作。

更新 getForecastFromCache() 函數,檢查 caches 對象是否在全局 window 對象中可用,如果是,請從緩存中請求數據。

public/scripts/app.js

 
// CODELAB: Add code to get weather forecast from the caches object.
if (!('caches' in window)) {
  return null;
}
const url = `${window.location.origin}/forecast/${coords}`;
return caches.match(url)
    .then((response) => {
      if (response) {
        return response.json();
      }
      return null;
    })
    .catch((err) => {
      console.error('Error getting data from cache', err);
      return null;
    });

然後,我們需要修改 updateData()以便它進行兩次調用,一次調用 getForecastFromNetwork() 以從網路獲取天氣預報,併發起另一次 getForecastFromCache() 以獲取緩存的最新天氣預報:

public/scripts/app.js

 
// CODELAB: Add code to call getForecastFromCache.
getForecastFromCache(location.geo)
    .then((forecast) => {
      renderForecast(card, forecast);
    });

我們的天氣應用現在發出兩個非同步數據請求,一個來自緩存,另一個來自 fetch 。如果緩存中有數據,它將被非常快速地返回和渲染(幾十毫秒)。然後,當 fetch 響應時,將使用直接來自天氣 API 的最新數據更新卡片。

請註意緩存請求和 fetch 請求如何結束於更新天氣預報卡片的調用。應用要如何知道它是否顯示了最新的數據?這在 renderForecast() 的如下代碼中處理:

public/scripts/app.js

 
// If the data on the element is newer, skip the update.
if (lastUpdated >= data.currently.time) {
  return;
}

每次更新卡片時,應用都會將數據的時間戳存儲在卡片上的隱藏屬性中。如果卡片上已存在的時間戳比傳遞給函數的數據新,應用就什麼也不做。

預先緩存我們的應用資源

在 Service Worker 中,讓我們添加一個 DATA_CACHE_NAME 以便我們可以將應用數據與應用外殼分開。更新應用外殼並清除舊緩存後,我們的數據將保持不變,仍用於超快速載入。請記住,如果你的數據格式將來發生了變化,你就需要一種方法來處理這種情況,並確保應用外殼和內容保持同步。

public/service-worker.js

 
// CODELAB: Update cache names any time any of the cached files change.
const CACHE_NAME = 'static-cache-v2';
const DATA_CACHE_NAME = 'data-cache-v1';

別忘了也要同時更新 CACHE_NAME,我們還將更改所有的靜態資源。

為了讓本應用離線工作,我們需要預先緩存它所需的所有資源。這也有助於提升性能。該應用無需從網路獲取所有資源,而是可以從本地緩存載入所有資源,從而消除任何網路不穩定性。

把 FILES_TO_CACHE 數組改為如下文件列表:

public/service-worker.js

 
// CODELAB: Add list of files to cache here.
const FILES_TO_CACHE = [
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、過濾器的兩個特征 1、他是一種特性,可以引用到控制器類和Action方法上。比如下圖 這裡控制器類和action方法都引用了過濾器,這個過濾器是用來做授權的 2、特征繼承自FilterAttribute 所以只要繼承了FilterAttribute,就可以實現自定義的過濾器 2、MVC框架的典型 ...
  • EF實體框架數據操作基類主要是規範增、改、查、分頁、Lambda表達式條件處理,以及非同步操作等特性,這樣能夠儘可能的符合基類這個特殊類的定義,實現功能介面的最大化重用和統一。 1、程式代碼 #region 00 單例模式 private static BaseDAL<T> _mInstance = ...
  • 也不知道之前裝VS2017的時候,做了什麼操作,新建一個WinForm項目,自動記住了我當時新建的窗體的大小816*639(預設的300*300),現在每次新建窗體都這個大小,忍了一段時間,實在忍無可忍了,網上找解決方案,一頓猛搜索,上窮百度下谷歌,兩處茫茫皆不見。得了,自己想轍唄! 首先判斷信息藏 ...
  • C# winform 自定義控制項之TextBox改PromtedTextBox 類似html標簽里input標簽里的placeHolder屬性,控制項繼承TextBox,擁有一個描述提示信息的欄位_txtPlaceHolder,重寫了消息處理函數WndProc,如果windows送出來的消息是繪製控制項... ...
  • 作為一個8歲開始學習編程,至今40歲的老程式員,這輩子使用過無數種語言,從basic開始,到pascal, C, C++,到後來的 java, c#,perl,php,再到現在流行的python。 小時候的我總覺得多掌握一門語言,我的技術能力就又前進了一步; 後來長大了慢慢明白,編程語言就和我們說的 ...
  • 本文首先簡單的介紹了IIS的安裝,以及如何將ASP.NET Web網站部署到我們的IIS當中,最後簡單的介紹了在項目開發期間我們如何將程式附加到IIS進程當中進行調試的。 ...
  • 非同步編程模型(TAP)提供了抽象的非同步代碼。非同步代碼看起來和同步代碼沒什麼大的區別,無非多個了兩個關鍵字(async和await)。但是代碼的執行順序並沒看起來那麼簡單,代碼的執行順序根據cpu資源的變化和任務完成的時間的不同而變化。這類似於人們為包含非同步任務的流程提供不同指令的操作一樣。 ...
  • WeihanLi.Npoi 導出支持自定義列內容啦 Intro 之前也有網友給提出過希望列合併或者自定義列內容的 issue 或請求,起初因為自己做 這個擴展的最初目的是導入導出的簡單化,使用這個擴展導出的 Excel/csv 可以直接導入成 ,所以如果涉及的列合併的話或者自定義列的話,可能就不能直 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...