AMP

將 AMP 作為 PWA 的資料來源

重要事項:本文件不適用於您目前選取的格式 ads

如果您已投資 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 何時可供使用?

我們建議您使用 async 屬性載入 Shadow AMP 函式庫。然而,這表示您需要使用某種方法來瞭解函式庫何時完全載入且可供使用。

要觀察的正確訊號是全域 AMP 變數的可用性,而 Shadow AMP 使用「非同步函式載入方法」來協助達成此目的。請考量以下程式碼

(window.AMP = window.AMP || []).push(function(AMP) {
  // AMP is now available.
});

此程式碼將可運作,且以這種方式加入的任何數量的回呼都確實會在 AMP 可用時觸發,但為什麼呢?

此程式碼會轉譯為

  1. 「如果 window.AMP 不存在,則建立一個空陣列來取代其位置」
  2. 「然後將回呼函式推送至陣列中,該函式應在 AMP 準備就緒時執行」

它可以運作,因為 Shadow AMP 函式庫在實際載入時,會意識到 window.AMP 下已存在回呼陣列,然後處理整個佇列。如果您稍後再次執行相同的函式,它仍然可以運作,因為 Shadow AMP 會將 window.AMP 替換為自身和自訂的 push 方法,該方法只會立即觸發回呼。

提示 – 為了使上述程式碼範例更實用,我們建議您將其包裝在 Promise 中,然後始終在使用 AMP API 之前使用所述 Promise。查看我們的 React 示範程式碼 以取得範例。

在您的 Progressive Web App 中處理導覽

您仍然需要手動實作此步驟。畢竟,連結在您的導覽概念中如何呈現內容取決於您。許多清單?一堆卡片?

在常見的情況下,您會擷取一些 JSON,其中傳回具有某些中繼資料的已排序 URL。最後,您應該得到一個在使用者按一下其中一個連結時觸發的函式回呼,而該回呼應包含所要求 AMP 頁面的 URL。如果您有該 URL,則一切都已準備就緒,可以進行最後一個步驟。

使用 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 之前,現在是移除在單獨顯示 AMP 頁面時有意義,但在內嵌模式下沒有意義的頁面元素的絕佳時機:例如,頁尾和頁首。

就是這樣!您的 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。

您也可以看到使用 Polymer 架構的 PWA 和 AMP 範例。此範例使用 amp-viewer 內嵌 AMP 頁面。