将 AMP 用作 PWA 的数据源
如果您已投资于 AMP 但尚未构建渐进式网络应用,那么您的 AMP 页面可以极大地简化您对渐进式网络应用的开发。在本指南中,您将了解如何在渐进式网络应用中使用 AMP,并将您现有的 AMP 页面用作数据源。
从 JSON 到 AMP
在最常见的场景中,渐进式网络应用程序是一个通过 Ajax 连接到 JSON API 的单页应用程序。然后,此 JSON API 返回数据集来驱动导航,以及用于呈现文章的实际内容。
然后,您将继续进行并将原始内容转换为可用的 HTML,并在客户端上呈现它。此过程成本高昂,且通常难以维护。相反,您可以将已有的 AMP 页面重新用作内容源。最棒的是,AMP 使得只需几行代码即可轻松做到这一点。
在您的渐进式网络应用中包含“影子 AMP”
第一步是在您的渐进式网络应用程序中包含一个我们称为“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>
您如何知道影子 AMP API 何时可以使用?
我们建议您使用 async
属性加载 Shadow AMP 库。但是,这意味着您需要使用某种方法来了解库何时完全加载并准备好使用。
要观察的正确信号是全局 AMP
变量的可用性,而 Shadow AMP 使用“异步函数加载方法”来帮助实现这一点。考虑以下代码
(window.AMP = window.AMP || []).push(function(AMP) { // AMP is now available. });
此代码将起作用,并且以这种方式添加的任何数量的回调都将在 AMP 可用时触发,但为什么?
此代码转换为
- “如果 window.AMP 不存在,创建一个空数组来代替它”
- “然后将一个回调函数推送到数组中,该回调函数应在 AMP 准备就绪时执行”
它之所以起作用,是因为 Shadow AMP 库在实际加载时会意识到 window.AMP
下已经有一个回调数组,然后处理整个队列。如果您稍后再次执行相同的功能,它仍然有效,因为 Shadow AMP 会用它自己和一个自定义的 push
方法替换 window.AMP
,该方法只需立即触发回调。
在您的渐进式网络应用中处理导航
您仍需要手动执行此步骤。毕竟,由您决定如何导航概念中内容的链接。一些列表?一堆卡片?
在常见场景中,您会获取一些 JSON,它会返回带有某些元数据的已排序 URL。最后,您应该会得到一个函数回调,该回调会在用户点击其中一个链接时触发,并且该回调应包括所请求 AMP 页面的 URL。如果您有此信息,则已准备好执行最后一步。
使用影子 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。在放弃先前渲染的 AMP 页面时,请务必告知 AMP,如下所示
// ampedDoc is the reference returned from AMP.attachShadowDoc ampedDoc.close();
这将告知 AMP 您不再使用此文档,并将释放内存和 CPU 开销。
立即查看
您可以在我们构建的 React 示例 中看到“PWA 中的 AMP”模式的实际应用。它展示了导航期间的平滑过渡,并附带一个简单的 React 组件,该组件封装了上述步骤。它融合了两全其美——渐进式网络应用中的灵活自定义 JavaScript,以及用于驱动内容的 AMP。
- 在此处获取源代码:https://github.com/ampproject/amp-publisher-sample/tree/master/amp-pwa
- 通过 npm 独立使用 React 组件:https://npmjs.net.cn/package/react-amp-document
- 在此处查看实际应用:https://choumx.github.io/amp-pwa/(最好在您的手机或移动模拟器上查看)
您还可以使用 Polymer 框架查看 PWA 和 AMP 样本。该样本使用 amp-viewer 嵌入 AMP 页面。
-
由 @pbakaus 撰写