在你的 PWA 中使用 AMP 作为数据源
重要提示:此文档不适用于你当前选择的格式 stories!
如果你已投入使用 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 可用时触发,但是为什么?
此代码转换为
- “如果 window.AMP 不存在,则创建一个空数组来占据其位置”
- “然后将一个回调函数推入数组,该回调函数应在 AMP 准备就绪时执行”
之所以起作用,是因为 Shadow AMP 库在实际加载后会意识到 window.AMP
下已经有一个回调数组,然后处理整个队列。如果你稍后再次执行相同的函数,它仍然会起作用,因为 Shadow AMP 会用自身和一个自定义 push
方法替换 window.AMP
,该方法会立即触发回调。
在你的渐进式 Web 应用中处理导航
你仍然需要手动实现此步骤。毕竟,如何在你导航概念中显示指向内容的链接取决于你。一些列表?一堆卡片?
在常见情况下,你将获取一些返回带有某些元数据的排序 URL 的 JSON。最后,你应得到一个当用户单击其中一个链接时触发的函数回调,并且该回调应包含所请求的 AMP 页面的 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 页面将作为你的整体渐进式 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 来驱动内容。
- 在此处获取源代码: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 撰写