將 AMP 作為 PWA 的資料來源
如果您已投資 AMP,但尚未建立 Progressive Web App,您的 AMP 頁面可以大幅簡化 Progressive Web App 的開發作業。在本指南中,您將瞭解如何在 Progressive Web App 中使用 AMP,並將現有的 AMP 頁面作為資料來源。
從 JSON 到 AMP
在最常見的情況下,Progressive Web App 是透過 Ajax 連線至 JSON API 的單頁應用程式。然後,這個 JSON API 會傳回多組資料,以驅動導覽,以及呈現文章的實際內容。
接著,您可以繼續將原始內容轉換為可用的 HTML,並在用戶端上呈現。這個程序既耗費成本,而且通常難以維護。您可以改為重複使用現有的 AMP 頁面作為內容來源。最棒的是,AMP 讓您只需幾行程式碼就能輕鬆完成。
在您的 Progressive Web App 中加入「Shadow AMP」
第一步是在 Progressive Web App 中加入特殊版本的 AMP,我們稱之為「Shadow AMP」。沒錯,您可以在頂層頁面中載入 AMP 程式庫,但它實際上不會控制頂層內容。它只會「放大」您告知它的頁面部分。
將 Shadow AMP 加入頁面的 head 中,如下所示
<!-- Asynchronously load the AMP-with-Shadow-DOM runtime library. --> <script async src="https://cdn.ampproject.org/shadow-v0.js"></script>
如何得知 Shadow AMP API 何時可供使用?
我們建議您載入 Shadow AMP 程式庫時,一併加入 async
屬性。然而,這表示您需要使用特定的方法來瞭解程式庫何時完全載入並可供使用。
要觀察的正確訊號是全域 AMP
變數的可用性,而 Shadow AMP 使用「非同步函式載入方法」來協助完成這項作業。請參考以下程式碼
(window.AMP = window.AMP || []).push(function(AMP) { // AMP is now available. });
這段程式碼可以運作,而且以這種方式加入的任何數量回呼,都確實會在 AMP 可用時觸發,但為什麼呢?
這段程式碼會轉譯為
- 「如果 window.AMP 不存在,請建立一個空陣列來佔用其位置」
- 「然後將回呼函式推送至應在 AMP 準備就緒時執行的陣列中」
它的運作原理是,Shadow AMP 程式庫在實際載入時,會發現 window.AMP
下方已經有一個回呼陣列,然後處理整個佇列。如果您稍後再次執行相同的函式,它仍然可以運作,因為 Shadow AMP 會將 window.AMP
取代為自身和自訂的 push
方法,而這個方法只會立即觸發回呼。
處理 Progressive Web App 中的導覽
您仍然需要手動實作這個步驟。畢竟,如何呈現導覽概念中內容的連結取決於您。多個清單?多張資訊卡?
在常見的情況下,您會擷取一些 JSON,其中傳回已排序的網址以及一些中繼資料。最後,您應該得到一個函式回呼,該回呼會在使用者按一下其中一個連結時觸發,而且所述回呼應包含所要求 AMP 頁面的網址。如果您有這個,就已為最後一個步驟做好準備。
使用 Shadow AMP API 以內嵌方式呈現頁面
最後,當您想要在使用者動作後顯示內容時,就該擷取相關的 AMP 文件,並讓 Shadow AMP 接管。首先,實作一個函式來擷取頁面,類似於這個函式
function fetchDocument(url) { // unfortunately fetch() does not support retrieving documents, // so we have to resort to good old XMLHttpRequest. var xhr = new XMLHttpRequest(); return new Promise(function(resolve, reject) { xhr.open('GET', url, true); xhr.responseType = 'document'; xhr.setRequestHeader('Accept', 'text/html'); xhr.onload = function() { // .responseXML contains a ready-to-use Document object resolve(xhr.responseXML); }; xhr.send(); }); }
現在我們有了隨時可用的 Document
物件,就該讓 AMP 接管並呈現它了。取得 DOM 元素的參照,該元素做為 AMP 文件的容器,然後呼叫 AMP.attachShadowDoc()
,如下所示
// This can be any DOM element var container = document.getElementById('container'); // The AMP page you want to display var url = "https://my-domain/amp/an-article.html"; // Use our fetchDocument method to get the doc fetchDocument(url).then(function(doc) { // Let AMP take over and render the page var ampedDoc = AMP.attachShadowDoc(container, doc, url); });
就是這樣!您的 AMP 頁面會呈現為整體 Progressive Web App 的子項。
自行清理
您的使用者很可能會在 Progressive Web App 內從一個 AMP 導覽到另一個 AMP。當捨棄先前呈現的 AMP 頁面時,請務必告知 AMP,如下所示
// ampedDoc is the reference returned from AMP.attachShadowDoc ampedDoc.close();
這會告知 AMP 您不再使用這個文件,並釋出記憶體和 CPU 額外負荷。
觀看實際運作情況
您可以在我們建構的 React 範例中看到「PWA 中的 AMP」模式的實際運作情況。它示範了導覽期間的順暢轉換,並隨附一個簡單的 React 元件,可包裝上述步驟。這是兩全其美的方法:Progressive Web App 中彈性的自訂 JavaScript,以及用於驅動內容的 AMP。
- 在此處取得原始碼:https://github.com/ampproject/amp-publisher-sample/tree/master/amp-pwa
- 透過 npm 以獨立方式使用 React 元件:https://www.npmjs.com/package/react-amp-document
- 在此處觀看實際運作情況:https://choumx.github.io/amp-pwa/ (最好在您的手機或行動裝置模擬器上觀看)
您也可以看到使用 Polymer 架構的 PWA 和 AMP 範例。這個範例使用 amp-viewer 來內嵌 AMP 頁面。
- 在此處取得程式碼:https://github.com/Polymer/news/tree/amp
- 在此處觀看實際運作情況:https://polymer-news-amp.appspot.com/
-
作者: @pbakaus