AMP

Использование AMP в качестве источника данных для вашего PWA

Если вы уже пользуетесь AMP, но еще не создали прогрессивное веб-приложение (PWA), ваши AMP-страницы могут значительно упростить его разработку. В этом руководстве вы узнаете, как использовать AMP в прогрессивном веб-приложении и задействовать существующие AMP-страницы в качестве источников данных.

От JSON к AMP

PWA, в своем наиболее распространенном сценарии применения, — это одностраничное приложение, которое подключается к JSON API по Ajax. JSON API возвращает наборы данных для определения структуры навигации и собственно контент для наполнения статей.

Далее вы преобразуете необработанный контент в пригодный к использованию HTML и визуализируете его на клиенте. Поскольку этот процесс является ресурсоемким и часто сложным в сопровождении, можно пойти другим путем — задействовать в качестве источника контента уже существующие AMP-страницы. И, что особенно важно, AMP позволяет осуществить это всего несколькими строчками кода.

Включение Shadow AMP в ваше прогрессивное веб-приложение

Первый шаг — включить в ваше прогрессивное веб-приложение специальную версию AMP, которую мы называем Shadow AMP. Да, это не ошибка — вы загружаете библиотеку AMP на странице верхнего уровня, но по факту она не будет контролировать контент верхнего уровня, а будет лишь «улучшать» те части страницы, которые вы выберете.

Добавьте Shadow AMP в шапку своей страницы, например так:

<!-- Asynchronously load the AMP-with-Shadow-DOM runtime library. -->
<script async src="https://cdn.ampproject.org/shadow-v0.js"></script>

Как узнать, что API Shadow AMP готов к использованию?

Мы рекомендуем загружать библиотеку Shadow AMP с атрибутом async. Однако в этом случае, чтобы определить, что библиотека полностью загружена и готова к использованию, необходим определенный подход.

Лучший маркер готовности — это глобальная переменная 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, который выполняет обратные вызовы незамедлительно.

СОВЕТ. Чтобы сделать приведенный выше пример кода практичным, рекомендуем обернуть его в Обещание, после чего всегда использовать это обещание, прежде чем работать с API AMP. Пример такого подхода вы можете увидеть в нашем демонстрационном коде на React.

Создание навигации по вашему прогрессивному веб-приложению

Это еще один шаг, который нужно выполнить вручную. В конце концов, именно вам решать, как в вашей концепции навигации будут представлены ссылки на контент (списки, набор карточек или что-то еще).

Обычный сценарий выглядит так: вы загружаете некий JSON-файл, содержащий упорядоченные URL с определенными метаданными. Вы также получаете функцию обратного вызова, которая срабатывает, когда пользователь нажимает на одну из ссылок, и этот обратный вызов должен включать URL-адрес запрошенной AMP-страницы. Если все это уже присутствует, вы готовы к последнему этапу.

Использование API Shadow AMP для встроенного рендеринга страницы

И наконец, чтобы отобразить контент после действия пользователя, пора загрузить нужный 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-страница отображается как дочерний элемент вашего прогрессивного веб-приложения.

Приберите за собой

Скорее всего, в рамках вашего прогрессивного веб-приложения пользователь будет переходить от одной AMP-страницы к другой. При уходе с ранее отрендеренной AMP-страницы обязательно уведомляйте об этом библиотеку AMP; это делается следующим образом:

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

Так вы сообщаете AMP, что больше не используете этот документ, что дает возможность высвободить память и ресурсы процессора.

Просмотр в действии

Увидеть паттерн «AMP в PWA» в действии можно в созданном нами примере на React. Он демонстрирует плавные переходы во время навигации и поставляется с простым компонентом React, в который включены описанные выше шаги. То, что вы увидите, является объединением лучших особенностей обеих технологий — гибкий, настраиваемый JavaScript в прогрессивном веб-приложении и AMP для предоставления контента.

Вы также можете ознакомиться с примером совместной работы PWA и AMP на базе Polymer Framework. В этом примере для встраивания AMP-страниц используется amp-viewer.