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 应用程序中包含一个我们称之为“Shadow AMP”的特殊版本 AMP。是的,没错,您可以在顶级页面中加载 AMP 库,但它实际上不会控制顶级内容。它只会“放大”您告诉它的页面部分。

将 Shadow AMP 包含在页面的头部,如下所示

<!-- 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 会用它自己和一个自定义的 push 方法替换 window.AMP,该方法会立即触发回调。

提示 – 为了使上面的代码示例实用,我们建议您将其包装在一个 Promise 中,然后在与 AMP API 一起使用之前始终使用该 Promise。有关示例,请查看我们的 React 演示代码

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

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

在常见情况下,您将获取一些 JSON,该 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 接管并渲染它了。获取对用作 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 页面。