摘要
聖誕老人追蹤器,在 2016 年節慶季節順利升級至離線漸進式網頁應用程式, 這都要歸功於現有場景設計
結果
- Santa 是一款漸進式網頁應用程式 (PWA),支援將內容新增至主畫面 (ATHS) 及離線運作
- 10% 符合資格的工作階段是透過 ATHS 圖示展開
- 75% 的使用者原生支援自訂元素和 shadow DOM (即網頁元件的兩個核心部分)
- Lighthouse 獲得 81 分
- 透過 Service Worker API 離線,系統會結合延遲載入功能,只快取造訪過的場景,並在新版本中自動升級
背景
聖誕老人追蹤器是 Google 的節慶傳統。 每年 12 月都有遊戲和教育體驗,歡迎踴躍參加! 當聖誕老人休息片刻時,小精靈們努力將聖誕老人追蹤器 包括網路和 Android:
網路上的「聖誕老人追蹤器」是一個大型的互動式網站,擁有許多獨特的「場景」,
聚合物:支援大部分新式瀏覽器。
評估使用者的瀏覽器是否為「現代化」會經由特徵偵測決定:
聖誕老人需要
Set
和
Web Performance API
和其他。
我們在 2016 年升級了聖誕老人追蹤器背後的引擎,並且支援大多數的離線體驗 場景。 不包括 YouTube 影片幕後的場景,或與聖誕老人實際地點相關的場景。 當然,只有與北極有直接關聯!📶☃️

挑戰
聖誕老人的回應式設計完美融合手機、平板電腦和桌上型電腦, 提供獨具風格的視覺效果和節慶主題音效等優質多媒體內容,讓你盡情觀賞網站。 但是,聖誕老人追蹤器的正常版本是數百 MB! 原因如下:
- 聖誕老人支援超過 35 種語言,因此許多素材資源都必須重複。
- 各平台提供的媒體支援有所不同 (例如 mp3 與 ogg)。
- 多媒體檔案有時會以不同大小和解析度提供。
聖誕老人的小精靈還在 12 月分擔努力不懈,往往會發布新的重大更新 一整個月 也就是說,使用者瀏覽器快取過的素材資源可能必須在回訪時重新整理。
這些挑戰:
- 不同「場景」的大型多媒體資源
- 異動內容會在當月生效
...導致無法隨意制定離線策略。
使用 Polymer 打造而成的聖誕老人
不妨先回頭討論聖誕老人的整體設計,再深入探究我們如何 並升級至離線 PWA
Santa 是一款單頁應用程式,最初是以 Polymer 0.5 寫成,現在已升級為 Polymer 1.7. 聖誕老人是由一組共用的程式碼組成,包括路由器、共用導航資產等。 它還有許多獨特的「場景」。

每個場景可透過不同的網址存取:/village.html
、/codelab.html
和
/boatload.html
:本身是網頁元件。
當使用者開啟場景時,我們會預先載入所有必要的 HTML 和素材資源 (圖片、音訊、css、js),
它位於聖誕老人追蹤器存放區的 /scenes/[[sceneName]]
下。
在此情況下,使用者會看到友善的預載器顯示進度。
透過這種做法,我們就不必在使用者未看到的場景中載入不必要的素材資源 (大量資料) 這也代表我們需要保留一個內部「快取資訊清單」設定所有必要的素材資源 每個場景。快取資訊清單是 JSON 檔案,儲存檔名與 MD5 雜湊值之間的對應關係 。
載入您使用的工具
這個模型能節省頻寬,只提供使用者造訪場景所需的資源, 而不是一次預先載入整個網站 聖誕老人追蹤器利用 Polymer 在執行階段升級自訂元素的能力,而不是在 載入時間。 請看以下程式碼片段:
<lazy-pages id="lazypages" selected-item="{{selectedScene}}" ... >
<dorf-scene id="village" route="village" icon="1f384" permanent
mode$="[[mode]]"
path$="scenes/dorf/dorf-scene_[[language]].html"
class="santa-scene" allow-page-scrolling></dorf-scene>
<boatload-scene route="boatload" icon="26f5"
path$="scenes/boatload/boatload-scene_[[language]].html"
loading-bg-color="#8fd7f7"
loading-src="scenes/boatload/img/loading.svg"
logo="scenes/boatload/img/logo.svg"
class="santa-scene"></boatload-scene>
聖誕老人追蹤器會按照下列步驟載入場景,例如boatload-scene
:
- 所有場景元素 (包括
<boatload-scene>
) 最初都未知,且全部視為HTMLUnknownElement
,當中有一些其他屬性。 - 所選場景變更時,系統會通知
<lazy-pages>
元素。 <lazy-pages>
元素會解析場景的元素和path
屬性,並載入 HTML 匯入scenes/boatload/boatload-scene_en.html
。 這包含 Polymer 元素及其相依元素。- 顯示友善的友善載入器。
- 載入並執行 HTML 匯入檔案後,
<boatload-scene>
會透明地升級至 真正的 Polymer 元素,充滿歡樂氣息。🎄🎉
但這個方法有一些挑戰。例如,我們不希望包含重複的網頁元件。
舉例來說,如果兩個場景使用共同元素 (例如paper-button
,我們會在建構作業中將其移除
程序,並改為將這項資訊加入聖誕老人的分享代碼中。
離線設計
多虧 Polymer 和 lazy-pages
,聖誕老人追蹤器已妥善分成多個場景。加上每
但每個情境都有專屬目錄
我們設計了聖誕老人追蹤器的服務工作人員,其核心功能是在
使用者的瀏覽器、注意共用程式碼和「場景」的差異
Service Worker 背後的理論是什麼?當使用者透過支援的瀏覽器載入您的網站時,
前端 HTML 可以要求安裝 Service Worker。
「聖誕老人追蹤器」的服務工作人員位於 /sw.js
。
這會觸發 install
事件,這會預先快取聖誕老人的所有共用程式碼,因此不需要採取任何行動
以便擷取。

Service Worker 安裝完成後即可攔截所有 HTTP 要求。 針對聖誕老人追蹤器,簡化的決策流程如下:
- 這項要求是否已快取?
- 太好了!傳回快取的回應。
- 這項要求是否與場景目錄相符 (例如「 scene/Shipload/shipload-scene_en.html」) 嗎?
- 執行網路要求,並將結果儲存在快取中,然後再傳回使用者。
- 否則,請執行一般網路要求。
我們的流程和 install
事件可讓聖誕老人追蹤器載入,就算使用者處於離線狀態也一樣。
不過,您只能使用使用者先前載入的場景。
非常適合重播遊戲並超越自己的最高分記錄。
阿肯觀察器可能會發現,我們的快取策略不允許內容「變更」。 檔案在使用者瀏覽器中快取後,將永遠無法變更。 稍後會再詳細討論。
實際操作
如先前所述,聖誕老人的小精靈們在整個 12 月都努力不懈,而且經常必須
整個月的更新內容。
拍攝聖誕老人追蹤器時,系統會為其加上一個專屬標籤,例如v20161204112055
,
版本的時間戳記 (2016 年 12 月 4 日 11:20:55)。
針對這個加上標籤的版本,我們會為每個檔案產生 MD5 雜湊,並將其儲存在「快取」中 資訊清單」。 在新型固態磁碟上,建構程序只會增加幾秒鐘的時間。
每個版本都會部署至 Google 靜態快取伺服器中獨特的路徑。 也就是說,較舊的版本一律不會遭到移除。 也就是說,在新版本發布後,所有素材資源都會使用不同的網址 (即使使用者沒有該網址) 變更—而瀏覽器或 Service Worker 快取的所有內容將無法使用,除非我們這麼做 也多了一點功夫
我們也會部署名為「prod」的新版本資源—聖誕老人的索引 HTML 和服務 工作站:前往 https://santatracker.google.com/。 這會覆寫舊版本。

每次載入聖誕老人追蹤器時,瀏覽器都會檢查已更新的 Service Worker,再加以擷取 (如果
廣告。
在本範例中,每個版本都會產生位元組不同的程式碼。
瀏覽器將此視為升級,並執行新的 install
事件。
這時,使用者的瀏覽器會檢查新的「快取資訊清單」。 系統會將這項資訊與使用者現有的快取進行比較,如果資產有不同的 MD5 雜湊,我們 請刪除快取,再要求瀏覽器重新擷取網頁。 不過,在大多數情況下,快取內容大致相同,或僅有細微差異。

在聖誕老人追蹤器中,升級 Service Worker 會使使用者的瀏覽器立即重新載入。
離線瀏覽體驗
當然,我們也對 UI 做了一些調整,以便支援離線體驗,以及 就算使用者可能並不希望網站離線,也能更容易理解。
離線瀏覽時會顯示小型橫幅。 所有未快取的場景都會「凍結」且無法點選 如此一來,使用者無法存取「缺貨中」的內容。

聖誕老人追蹤器會定期向聖誕老人 API 發出要求。
如果這些要求失敗或逾時,我們會假設使用者處於離線狀態。
我們使用這個 API,而不是瀏覽器內建的 navigator.onLine
屬性:這項操作只會
通知我們該使用者是否可能在線上(也稱為 Lie-Fi)。
國際連線
雖然我們大多數使用者都使用英文 (後面依序加上日文、葡萄牙文、西班牙文和 法語) 所開發,並推出超過 35 種語言版本。
當使用者載入聖誕老人追蹤器時,我們會使用 瀏覽器的語言 和其他提示選擇要放送的語言 但大多數使用者絕不會覆寫這個語言。 不過,如果使用者透過選擇器選擇新語言,我們就會視為 提供的 Fitbit 裝置,就像上述情況,當聖誕老人追蹤器推出新版本時一樣。

換句話說,為配合 Service Worker 用途,請安裝最新版本的聖誕老人追蹤器 其實是 (build,language) 的元組。
新增至主畫面
聖誕老人離線運作且為服務工作人員提供服務,系統會提示符合資格的使用者進行安裝 並返回主畫面。 2016 年,約有 10% 的合格載入內容是來自主畫面圖示。
結論
我們可以將聖誕老人追蹤器快速轉換成離線 PWA,為使用者打造可靠又引人入勝的 PWA 但有了目前的場景設計,我們只需使用現有的 Polymer 和 網頁元件 此外,這個平台也會運用我們的建構系統執行有效率的升級作業,而且只會撤銷已變更的資產。
雖然聖誕老人是自訂的解決方案,但他們的許多原則可以在 Polymer 中找到 專案的 App Toolbox。 如果您要從頭開始建構新的 PWA,或想找出 則建議使用 Workbox 程式庫。