Разработчики часто получают запросы от клиентов, которые не всегда логичны или продвигают передовой опыт; но даже в этом случае они часто представляют интересный шанс бросить вызов самим себе. Пытаясь соответствовать требованиям, мы часто сразу же сталкиваемся с проблемой, не задумываясь о завершении.

Не так давно я оказался в похожей ситуации с клиентом, который попросил использовать фреймворк AMP на полпути проекта. На это решение могли повлиять преимущества AMP, но это было серьезным ударом по текущему развитию. Первоначально была запрошена платформа Vue.js, которая активно использует JavaScript, в то время как AMP ограничивает использование CSS и запрещает использование JavaScript в проекте. Зная, что если начинать с нуля или переходить на другую платформу SSR, мы рискуем не завершить проект вовремя, наша команда решила перейти на Nuxt.js. Таким образом, мы могли использовать все уже созданные компоненты, представления и логику. при добавлении SSR, который позволит использовать AMP.

В этой статье мы рассмотрим проблемы, с которыми я столкнулся при создании веб-сайта с использованием AMP и Nuxt.js. Этот пост написан при условии, что читатель уже знаком с HTML, CSS, JavaScript, Vue.js и, возможно, Nuxt.js.

Заявление об ограничении ответственности

Этот пост ни в коем случае не является подробным руководством и не продвигает передовой опыт комбинирования этих двух фреймворков. Он был написан как практический пример для использования в качестве примера или ссылки другими людьми, которые могут оказаться в аналогичных обстоятельствах из-за отсутствия других примеров при попытке описанного выше.

Что такое Nuxt.js?

Nuxt.js - это фреймворк с открытым исходным кодом, основанный на Vue.js. Как описано на официальном сайте:

Его основная область применения - рендеринг пользовательского интерфейса при абстрагировании от клиент-серверного распределения.

Наша цель - создать достаточно гибкий фреймворк, чтобы вы могли использовать его в качестве основной базы проекта или в дополнение к вашему текущему проекту на основе Node.js.

Nuxt.js предустановил всю конфигурацию, необходимую для того, чтобы сделать разработку приложения Vue.js с серверным рендерингом более увлекательной.

В этой статье Nuxt используется специально из-за его эффективности при разработке веб-сайта SSR Vue.js.

Что такое усилитель?

Accelerated Mobile Pages или AMP - это платформа с открытым исходным кодом, поддерживаемая Google с целью ускорить отображение содержимого веб-страницы для мобильных пользователей в связи с увеличением числа людей, просматривающих Интернет через свои смартфоны. Или, как сказали бы на официальном сайте AMP:

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

Таким образом, AMP должен увеличивать скорость загрузки ваших страниц, помогать вам привлекать и удерживать мобильный трафик за счет улучшения вашего SEO-рейтинга за счет соблюдения строгих правил его реализации, таких как:

  • нет внутреннего или стороннего Javascript
  • Ограничения HTML-тегов
  • только встроенный пользовательский стиль, ограниченный 50 КБ, и некоторые дополнительные правила CSS

На первый взгляд, AMP не похож на интуитивно понятный подход, который может использовать разработчик. Однако, поскольку есть обещание повысить рейтинг SEO, и особенно потому, что это обещание исходит ни от кого иного, как от самого Google, нет ничего необычного в том, что AMP привлекает внимание клиентов, которые не хотят ничего, кроме того, чтобы их продукт был обнаружен.

Давайте начнем!

Поскольку демонстрация частей реального проекта, конечно, запрещена, мы решили продемонстрировать некоторые препятствия, с которыми мы столкнулись, создав демонстрацию, содержащую целевую страницу сайта потокового видео (называемого Home Theater), а также страницу со списком , реализующий разбиение на страницы.

Примечание.

Для создания этой демонстрации мы использовали OMDb’s (Open Movie Database) API, который представляет собой веб-службу RESTful для получения информации о фильмах. Чтобы использовать этот API, вам необходимо создать учетную запись, после чего вы получите ключ API, необходимый для получения информации.



Мы начали с инициализации проекта Nuxt.js по умолчанию, как указано в их руководстве, выполнив одну из следующих команд:

npx create-nuxt-app <project-name>

or

yarn create nuxt-app <project-name>

Мы решили назвать наш проект nuxt-amp-home-theather и использовали следующие варианты:

? Project name <project-name>
? Project description <project-description>
? Author name <your name>
? Choose the package manager <npm or yarn>
? Choose UI framework None
? Choose custom server framework Express
? Choose Nuxt.js modules Axios
? Choose linting tools ESLint, Prettier
? Choose test framework None
? Choose rendering mode Universal (SSR)

В нашем случае мы выбрали yarn в качестве диспетчера пакетов, и поэтому с этого момента все данные команды будут использовать yarn. Благодаря этому у нас есть проект по умолчанию, который мы можем легко просмотреть, запустив:

yarn dev

Внедрение AMP

После вышеупомянутой инициализации нам нужно внести некоторые изменения в nuxt.config.js, чтобы мы могли использовать AMP. К счастью, команда Nuxt подготовила пример AMP, который можно найти здесь:



Как видно из примера, помимо данных изменений в файле конфигурации нам также необходимо добавить файлapp.html. Но это не все. Поскольку AMP допускает только встроенный CSS и только один тег <style amp-custom>, нам также необходимо решить проблему стилей, написанных в каждом компоненте.

В приведенном выше примере это решается путем перемещения всех стилей в один файл - main.css, который затем вставляется Nuxt на каждую страницу. Затем с помощью ловушки render:route атрибут amp-custom добавляется к тегу <style>. Хотя это хорошее решение, оно также имеет свои недостатки.
Во-первых, вам придется записать все стили в один файл, что не улучшит впечатления разработчиков, если вы не используете несколько файлов и не импортируете все в один главный файл. Кроме того, если у вас есть несколько компонентов, и если не все из них используются на каждой странице, у вас будет неиспользуемый CSS на каждой из ваших страниц. Не говоря уже о том, что AMP накладывает ограничение на размер 50 КБ, поэтому ваш объединенный CSS не должен превышать этот размер.

По этим причинам мы решили попробовать другой подход, который заключался в том, чтобы оставить CSS как есть для каждого компонента. Когда Nuxt визуализирует каждый сайт, он будет включать только необходимый CSS, и все, что нам нужно сделать, это объединить их все в хук render:route. Мы можем сделать это, удалив строку, которая добавляет атрибут amp-custom к добавленному CSS, и заменив ее следующим кодом:

Как видно из приведенного выше кода, мы удаляем все теги стиля и объединяем все их содержимое. После этого мы просто добавляем все содержимое в один тег <style amp-custom> в конце тега <head>. Стоит отметить, что объединенный контент не минимизируется, поэтому вы можете использовать библиотеку для его минимизации, чтобы еще больше уменьшить его размер (например, clean-css).

Домашняя страница

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

Содержание домашней страницы довольно простое, состоит всего из двух частей: баннера и короткого списка популярных фильмов. Содержание домашней страницы выглядит так:

Мы передаем список фильмов, полученных из API OMDb, как banner, так и movie-list компонент. Последний также довольно простой, это просто список изображений, отображаемых в виде пояса. Поскольку мы показываем изображение, мы должны использовать тег amp-img в соответствии с инструкциями AMP:

Компонент banner, с другой стороны, отображает только логотипы приложения, Nuxt и AMP, а также карусель с афишами фильмов. Как вы могли заметить, мы используем компонент amp-carousel для отображения карусели, поскольку собственный JavaScript не разрешен.

На этом наша домашняя страница готова, однако, если мы попытаемся отобразить ее и добавить #development=1 в конце URL-адреса, мы увидим ошибку, касающуюся атрибута autoplay элемента карусели. Проблема в том, что Nuxt отображает этот атрибут со значением: autoplay="autoplay", в то время как AMP настоятельно требует, чтобы он не имел либо значения для бесконечного цикла, либо числа, указывающего количество циклов, после которых автоматическое воспроизведение остановится.
После некоторого просмотра , мы не смогли найти способ отключить это автоматическое присвоение значений, и поэтому приступили к решению этой проблемы, добавив следующую строку в метод themodifyHtml в файле конфигурации:

html = html.replace(/<amp-carousel([^>]*)>/gi, match => {
  return match.replace('autoplay="autoplay"', 'autoplay')
})

Страница серии

Вторая страница содержит просто список фильмов, а также компонент нумерации страниц для перемещения по страницам.

В отличие от домашней страницы, где список был визуализирован только один раз на стороне сервера для представления пользователю, здесь нам нужно обновлять список по мере прохождения страниц. По этой причине мы используем компонент amp-list вместе с настраиваемым компонентом разбивки на страницы.
Читая документацию AMP об этом компоненте, становится очевидным, что он более удобен для бесконечной прокрутки, чем для отображения с разбивкой на страницы. Однако, поскольку он требует, чтобы ответ JSON содержал URL-адрес следующей страницы, а API OMDb этого не делает, мы не можем реализовать бесконечную прокрутку. Вместо этого мы должны вручную изменить URL-адрес usingamp-bind. Эта функциональность позволяет вам изменять значения атрибутов аналогично Vue.
Для этого AMP позволяет поддерживать переменную с помощью компонента amp-state, поскольку использование JavaScript не допускается.

В нашем случае мы изменяем URL-адрес с помощью состояния (переменной) currentPage, которое мы поддерживаем в компоненте pagination.

Стимулирование компонента разбивки на страницы без возможности использования JavaScript, требовало использования нескольких amp-state компонентов и обновления каждого с помощью метода on:"tap:AMP.setState()".
Нам нужно инициализировать несколько состояний, а это можно сделать, только предоставив URL-адрес API или используя тег <script type="application/json">. Поскольку мы используем состояния как переменные для разбивки на страницы, нам нужно использовать тег script. Это представляет проблему, поскольку мы ранее настроили функцию modifyHtml render для удаления всех тегов скриптов. Следовательно, нам нужно изменить эту часть, чтобы исключить теги type="application/json".

После модификации окончательная версия функции modifyHtml должна выглядеть так:

Вы можете заметить, что мы также добавляем несколько скриптов сразу после удаления уже существующих. Это обязательные сценарии, которые необходимо включить, чтобы иметь возможность использовать различные компоненты AMP.

На этом наш демонстрационный проект готов и его можно развернуть. Для этого сообщения в блоге мы использовали Heroku, но разработчик должен выбрать, какая платформа лучше всего подходит для него. Поскольку развертывание проекта Nuxt не является целью этого поста, мы не будем вдаваться в подробности по этому поводу. Тем, кто заинтересован в развертывании с Heroku, я предлагаю вам взглянуть на сообщение в блоге ниже.



Вы можете посетить нашу развернутую демо-версию здесь и посмотреть репо проекта здесь.

Заключение

Демонстрируя вышеуказанный проект, мы видим, что можно комбинировать Nuxt (Vue) и AMP. Эта комбинация прибывает во время начальной загрузки страницы, так как нам нужно настроить HTML-код, сгенерированный Nuxt, чтобы он подходил для AMP. После начальной загрузки страницы должны быть кэшированы, поэтому любая последующая загрузка должна выполняться быстрее.

Однако, поскольку Nuxt является фреймворком, зависящим от JavaScript, а AMP требует удаления всего остального JavaScript, я считаю, что использование обоих немного противоречит здравому смыслу. Поэтому я бы посоветовал тщательно обдумать цель и потенциальные цели проекта, прежде чем начинать его разработку, чтобы с самого начала можно было выбрать правильную структуру.

Тем не менее, направление проекта не всегда ясно и не всегда остается неизменным. Итак, я надеюсь, что этот пост поможет тем, кто может оказаться в ситуации, аналогичной нашей.