AMP

将 AMP 用作 PWA 的数据源

重要提示:此文档不适用于您当前选择的格式 广告

如果您已经投资了 AMP 但尚未构建渐进式 Web 应用程序,那么您的 AMP 页面可以极大地简化您的渐进式 Web 应用程序的开发。在本指南中,您将学习如何在渐进式 Web 应用程序中消费 AMP,并将您现有的 AMP 页面用作数据源。

从 JSON 到 AMP

在最常见的情况下,渐进式 Web 应用程序是一个通过 Ajax 连接到 JSON API 的单页应用程序。然后,此 JSON API 返回数据集以驱动导航,以及渲染文章的实际内容。

然后,您将继续并将原始内容转换为可用的 HTML 并在客户端上渲染。此过程成本高昂且通常难以维护。相反,您可以重复使用您已经存在的 AMP 页面作为内容源。最重要的是,AMP 只需几行代码即可轻松实现。

在您的渐进式 Web 应用程序中包含“Shadow AMP”

第一步是在您的渐进式 Web 应用程序中包含一个特殊版本的 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 演示代码以获取示例。

在您的渐进式 Web 应用程序中处理导航

您仍然需要手动实现此步骤。毕竟,由您决定如何在导航概念中呈现内容的链接。一些列表? 一堆卡片?

在常见情况下,您会获取一些返回带有某些元数据的有序 URL 的 JSON。最后,您应该得到一个在用户单击其中一个链接时触发的函数回调,并且该回调应包含所请求 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 接管并渲染它了。获取对用作 AMP 文档容器的 DOM 元素的引用,然后调用 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 页面呈现为您整个渐进式 Web 应用程序的子项。

清理你的工作

您的用户很可能会在您的渐进式 Web 应用程序中从一个 AMP 导航到另一个 AMP。当丢弃之前渲染的 AMP 页面时,始终确保通知 AMP,如下所示

// ampedDoc is the reference returned from AMP.attachShadowDoc
ampedDoc.close();

这将告诉 AMP 您不再使用此文档,并将释放内存和 CPU 开销。

实际演示

您可以在我们构建的 React 示例中看到“PWA 中的 AMP”模式的实际效果。它演示了导航期间的平滑过渡,并带有一个简单的 React 组件来包装上述步骤。它是两全其美 - 渐进式 Web 应用程序中灵活的自定义 JavaScript,以及驱动内容的 AMP。

您还可以看到使用 Polymer 框架的 PWA 和 AMP 的示例。该示例使用 amp-viewer 来嵌入 AMP 页面。