Итак, вы хотите использовать свой причудливый компонент React на веб-сайте AMP и хотите знать, как это сделать. Я приглашаю вас присоединиться ко мне в моем путешествии, пытаясь заставить его работать.
Ускоренные мобильные страницы
Но сначала давайте напомним себе, что такое AMP на самом деле.
AMP (первоначально аббревиатура от Accelerated Mobile Pages) - это структура веб-компонентов и технология публикации веб-сайтов, разработанная Google, цель которой - «предоставлять формат, ориентированный на пользователя, для веб-контента».
Возможно, AMP ориентирован на пользователя, но в Интернете можно найти множество доказательств того, что это не совсем платформа, ориентированная на разработчиков. AMP имеет очень строгие правила, он накладывает существенные ограничения и лимиты на содержание страницы. Например, до недавнего времени было невозможно использовать пользовательский JavaScript на страницах AMP, но был добавлен тег amp-script
, чтобы «разрешить запуск пользовательского JavaScript для визуализации пользовательского интерфейса».
Говоря об ограничениях, в нашем проекте некоторые страницы уже достигли ограничения на общий размер стиля (размер правил CSS, которые мы включаем на страницу), поэтому мы решили попробовать отрендерить довольно большое навигационное меню с помощью amp-script
. Наше меню было реализовано как компонент React, в нем была изрядная логика и стиль для разных брендов. Мы надеялись повторно использовать существующий код и сэкономить время на его повторной реализации с использованием собственных решений AMP.
И это то, что я узнал, пытаясь заставить это работать.
Обратите внимание, что это сообщение в блоге не является учебным пособием, и ваш результат может отличаться.
amp-скрипт
Согласно документации:
amp-script
запускает ваш пользовательский JavaScript в Web Worker, который содержит виртуальную модель DOM. Когда ваш код JavaScript изменяет эту виртуальную модель DOM, amp-script пересылает эти изменения в основной поток и применяет их к поддереву элемента amp-script.
Чтобы загрузить пользовательский JavaScript на свою страницу, вы должны использовать тег amp-script
с атрибутом src
.
<amp-script layout="container" src="https://example.com/hello-world.js"> <button>Hello amp-script!</button> </amp-script>
Будет загружен удаленный скрипт, и ему будет разрешено изменять содержимое внутри amp-скрипта.
Довольно аккуратно, но давайте проверим ограничения:
- Максимум 150 000 байт для всех элементов amp-script на странице;
- DOM API частично ограничен (см. Таблица или совместимость).
Здесь вы можете увидеть первую проблему: минимизированный размер React Core + React DOM составляет 109 КБ (согласно измерениям для v16), и если вы добавите styled-components
, который мы используем для наших компонентов, вы получите более 160 КБ.
Итак, должны ли мы отказаться от надежды на повторное использование кода и снова обвинить разработчиков Google? Может быть, но не обязательно!
Как насчет Preact?
По данным preactjs.com:
Preact - это быстрая альтернатива React объемом 3 КБ с тем же современным API.
3кб? Звучит многообещающе! И самое главное Preact совместим с компонентами React благодаря модулю preact/compat
.
Конечно, добавление дополнительной структуры к вашей кодовой базе реакции может усложнить процесс сборки, но мы хотим повторно использовать наш код, верно?
Для начала создадим простой компонент с помощью Preact:
import { Component } from 'preact'; export default class App extends Component { render() { return ( <div id="app"> Hi there! </div> ); } }
После того, как мы соберем бандл и свяжем его с amp-script
<amp-script layout="container" src="http://localhost:8000/js/amp.80f7b.js" > <div className="app">loading...</div> </amp-script>
мы получаем это:
Потрясающий! И размер нашего бандла по-прежнему невелик: 16кб.
Как я уже упоминал, в проекте мы используем styled-components
, поэтому давайте попробуем его в действии:
import { Component } from 'preact'; import styled from 'styled-components'; const StyledHeader = styled('h1')` color: green; `; export default class App extends Component { render() { return ( <div id="app"> <StyledHeader>Hi there!</StyledHeader> </div> ); } }
Как ни странно, мы получаем сообщение об ошибке: «Uncaught TypeError: невозможно прочитать свойство childNodes of undefined».
styled-components
создать стиль для каждого стилизованного компонента в head
, но amp-script
отображает содержимое в какой-то «песочнице», а document.head
в ней не существует, поэтому это не удается.
Для этого есть решение styled-components@v5
(сейчас в бета-версии), позволяющее указывать цель для его стилей:
import { Component } from 'preact'; import styled, { StyleSheetManager } from 'styled-components'; const StyledHeader = styled('h1')` color: green; `; export default class App extends Component { render() { return ( <div id="app"> <StyleSheetManager disableCSSOMInjection target={window.document.body}> <StyledHeader>Hi there!</StyledHeader> </StyleSheetManager> </div> ); } }
Сейчас ошибок нет, но стиль не применялся (текст должен был иметь зеленый цвет):
Очевидно, amp-script
фильтрует style
теги, и в результате на страницу не добавляются никакие стили.
Мне пока не удалось найти решение этой проблемы, поэтому я решил попробовать отрендерить наш компонент меню и разобраться с этим позже. Для его рендеринга нам нужно добавить пару провайдеров и сам компонент:
export default class App extends Component { render() { return ( <div id="app"> <StyleSheetManager disableCSSOMInjection target={window.document.body}> <ThemeProvider market="uk"> <ConfigProvider> <Menu {...menuProps} /> </ConfigProvider> </ThemeProvider> </StyleSheetManager> </div> ); } }
Все работает локально, как ожидалось, поэтому мы добавляем наш пакет на страницу AMP и снова получаем сообщение об ошибке: [amp-script] Превышен максимальный общий размер скрипта (150000).
В нашем пакете JavaScript теперь 177 КБ! Тогда это не шанс ...
Хотя я ценю цель платформы AMP, заключающуюся в обеспечении удобного взаимодействия с пользователем, AMP по-прежнему очень ограничен и не позволяет использовать современный набор инструментов для разработки. Я считаю, что это очень прискорбно, что современная веб-разработка имеет такой плохой случай прожорливости, и очень трудно сделать производительное и эффективное решение, не слишком сильно увеличивая размер страницы.
Что все это значит для нас? Может быть, мы будем использовать amp-script
для чего-нибудь еще.