HTMX может иметь большое значение для WordPress

Опубликовано: 2024-05-10

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

Дней с момента последней разработки JS-фреймворка.

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

Но что, если так не должно было быть? В этой статье мы рассмотрим, как современные веб-интерфейсы создаются с помощью JavaScript, трудности, с которыми сталкиваются разработчики, и альтернативу, предлагаемую HTMX. В частности, мы рассмотрим, почему HTMX и WordPress могут быть идеальной парой, заключенной на небесах.

Как мы сюда попали

До появления JavaScript браузеры были просто прославленными читателями документов. Таким образом, большая часть веб-приложений представляла собой «многостраничные приложения», или сокращенно MPA. MPA — это веб-приложения, состоящие из нескольких HTML-документов, по одному для каждой страницы приложения. Когда пользователь использует приложение, ему отображаются разные документы с разными доступными действиями.

MPA очень просто построить. Навигация осуществляется с помощью тегов <a> для связи с другими документами, а пользовательский ввод может быть зафиксирован с помощью элемента <form> . Сервер отвечает на запросы ссылок и форм новыми HTML-документами, заменяя страницу, отображаемую на экране.

Хорошим примером MPA, с которым вы, вероятно, хорошо знакомы, является WP Admin. Каждая страница администратора представляет собой документ с HTML, созданный PHP-кодом WordPress, работающим на сервере. Большинство страниц в WP Admin, например страницы настроек WordPress, как правило, состоят из форм, которые вы, пользователь, можете отправить.

И наоборот, одностраничное приложение, или SPA, — это приложение, использующее одну HTML-страницу. Навигация и пользовательский ввод затем обрабатываются кодом JavaScript, динамически изменяя части страницы на месте без необходимости заменять всю страницу или обновлять ее. Это приводит к более плавному и более отзывчивому пользовательскому интерфейсу.

В наши дни многие веб-приложения используют SPA для своего веб-интерфейса. В RebelCode мы создали SPA для интерфейсов администратора двух наших основных плагинов WordPress: Spotlight и Aggregator. Относительно новый редактор сайтов в WordPress также является SPA, как и блочный редактор сообщений.

Цена, которую мы платим

SPA — это собственные приложения, написанные на JavaScript и работающие в браузере. Их собственное определение также является их самым большим предостережением: у них нет немедленного доступа к ресурсам сервера. Это означает, что нам необходимо установить канал связи между SPA и сервером.

Давайте создадим простой плагин WordPress в качестве примера. Этот плагин предоставляет
простой пользовательский интерфейс CRUD для управления книгами. Внутренний API плагина на сервере может выглядеть примерно так:

 <?php function get_books(?int $count = null, int $page = 1): Book[]; function get_book(int $id): Book; function insert_book(Book $book): Book; function update_book(Book $book): Book; function delete_book(int $id): void;

Чтобы создать наш современный интерфейс SPA, мы будем использовать среду JavaScript, такую ​​​​как React; самый популярный фреймворк JavaScript, который также используется WordPress. Начнем с добавления страницы администратора:

 <?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }

Наша страница будет отображать один пустой элемент <div> , который будет служить корнем нашего приложения React, где будет отображаться остальная часть пользовательского интерфейса.

 const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }

Итак, как нам составить список книг, хранящихся в базе данных? Код для этого находится на сервере, поэтому нам нужен способ вызвать его и получить результат.

Для этого мы можем предоставить JSON API с сервера. Затем приложение React может сделать запрос по URL-адресу нашего API, получить книги в формате JSON, а затем отобразить список. В этом примере предположим, что мы добавили конечную точку в REST API WordPress:

 GET https://my-wp-site.com/wp-json/books { "books": [ { "id": 15, "title": "Mistborn", "author": "Brandon Sanderson", }, { "id": 44, "title": "The Hobbit", "author": "JRR Tolkien", }, ] }

Затем мы можем написать компонент React, который извлекает книги и отображает их в виде списка:

 function BookList() { const [books, setBooks] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect( function () { setIsLoading(true); fetch("https://my-wp-site.com/wp-json/books") .then((res) => res.json()) .then((data) => setBooks(data.books)) .else((error) => setError(error)) .finally(() => setIsLoading(false)); }, [setBooks, setIsLoading], ); if (isLoading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error}</div>; } return ( <ul> <li> {books.map((book) => ( <a key={book.id} href={book.url}> {book.title} </a> ))} </li> </ul> ); }

Но это решение слишком наивно и создает неприятные впечатления для пользователя. Он не учитывает изменения состояния после отсоединения компонента, кэширования ответа, повторной попытки неудачных запросов или предотвращения перезаписи устаревшего состояния более недавнего состояния. На самом деле, то, как мы используем fetch() в эффекте React, обычно не рекомендуется.

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

Но все это начинает казаться непропорционально большим усилием только для того, чтобы отобразить список книг. Действительно ли нам нужно создавать приложение JavaScript и API JSON, чтобы обеспечить удобство взаимодействия с пользователем?

Давайте сравним это с MPA, где отображение списка книг может быть выполнено всего за несколько строк PHP-кода без каких-либо зависимостей:

 <?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }

Но, конечно, это не корректное сравнение. Этот список книг представляет собой просто статический HTML; он не реагирует на изменения состояния или ввод пользователя.

Если мы хотим получить опыт, подобный SPA, при одновременном рендеринге HTML на сервере, где наш код имеет непосредственный доступ к базе данных, нам нужно найти способ, чтобы HTML, отображаемый на сервере, попадал в браузер. и замените предыдущий список книг. Но добиться этого без кода JavaScript в настоящее время невозможно, поэтому нам придется стиснуть зубы и все равно использовать JavaScript.

Но нам не нужно писать это самим.

Представляем HTML-код

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

Это совершенно другой подход к SPA, поскольку мы не создаем клиентское приложение JavaScript для обновления текущей страницы. Вместо этого мы просто добавляем некоторые атрибуты HTML, чтобы сообщить HTMX, как мы хотим, чтобы страница менялась при возникновении определенных событий.

Даже без HTMX вы уже можете изменить то, что отображается на экране, используя только HTML, хотя и очень ограниченно. Вы уже знакомы с этой функцией HTML: скромным элементом ссылки <a> .

 <a href="https://my-wp-site.com/books">View books</a>

Элемент ссылки предоставляет браузеру всю информацию, необходимую для навигации. При нажатии на него браузер берет href из элемента, выполняет запрос по этому URL-адресу, загружает ответ и, предполагая, что он содержит HTML, заменяет содержимое страницы новым HTML.

Элемент <form> — еще один пример того, как HTML может запрашивать новый HTML.

 <form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>

На этот раз браузер собирает значения из всех входных данных формы, отправляет их на сервер, загружает ответ и отображает его на экране.

Почему только <a> и <form> должны иметь возможность отправлять HTTP-запросы? Почему вы должны иметь возможность заменить только весь экран?

Из файла readme на GitHub HTMX.

Что ж, HTMX меняет это.

 <a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>

Благодаря атрибуту hx-target HTMX щелчок по ссылке теперь поместит ответ с https://my-wp-site.com/books внутри элемента с идентификатором "books" . Конечно, встраивание одной страницы в другую не является целью здесь. Нашему серверу не обязательно отвечать полной страницей, вместо этого он может просто ответить фрагментом HTML.

Предоставляя фрагменты HTML с нашего сервера и сообщая HTMX, как, откуда и когда получить эти фрагменты, мы можем создать веб-приложение, подобное SPA, без какого-либо JavaScript, где сервер полностью контролирует ситуацию. В каком-то смысле HTML стал нашим новым JSON.

И все, что нам нужно сделать, это загрузить HTMX-скрипт на нашу страницу:

 <script src="https://unpkg.com/[email protected]"></script>

(Обязательно ознакомьтесь с инструкциями в документации HTMX, поскольку приведенный выше код может быть устаревшим).

Давайте посмотрим на другой пример:

 <button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>

Здесь происходит еще много всего, поэтому давайте разберемся:

  • hx-get указывает URL-адрес для отправки запроса GET при нажатии кнопки.
  • hx-target="this" сообщает HTMX заменить нажатую кнопку ответом.
  • hx-swap="outerHTML" сообщает HTMX заменить всю кнопку, а не только то, что находится внутри нее.

В совокупности это сообщает HTMX:

При нажатии кнопки отправьте запрос GET на /button/off и замените эту кнопку ответом.

Допустим, сервер отвечает на /button/off приведенным ниже HTML-кодом:

 <button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>

Вы видите разницу? Атрибут hx-get теперь указывает на /button/on а текст внутри кнопки теперь «Включить». При нажатии этой кнопки она также будет заменена ответом от /button/on . Как вы можете себе представить, мы можем заставить сервер ответить исходной кнопкой, чтобы завершить наше переключение!

Эта простая идея, позволяющая любому элементу запрашивать новый HTML-код с сервера и решать, куда он будет направлен, оказывается весьма мощной. Мы можем создавать вкладки, выполнять поиск с живыми результатами, индикаторами выполнения и многим другим.

За и против

В отличие от большинства фреймворков JavaScript, HTMX не требует компиляции и связывания кода нашего клиентского приложения. Уже одно это является огромным преимуществом; Системы сборки JavaScript могут быть чрезвычайно сложными в настройке и обслуживании, особенно когда вы начинаете внедрять более экзотические функции и библиотеки, такие как TypeScript, JSX, препроцессоры CSS и т. д. Средние и крупные команды нередко имеют один или несколько участников, посвященных этой задаче.

Еще одним очевидным преимуществом является отсутствие отдельного клиентского приложения. Поскольку все, что нам нужно, это HTTP-сервер, который отвечает HTML, мы можем использовать любой язык программирования, который нам нравится. Это может быть для вас большим преимуществом, если ваша команда не знакома с современным JavaScript или недостаточно велика, чтобы оправдать создание двух приложений. Это может быть особенно заманчиво, если вы разработчик плагинов WordPress, поскольку вы можете использовать PHP для всех аспектов вашего плагина.

Но, пожалуй, самое важное преимущество заключается в том, что вам больше не нужен API между серверной и внешней частью вашего приложения. Это может сэкономить огромное количество времени на разработку, а также уменьшить объем кода, который может создавать ошибки, что также экономит время в долгосрочной перспективе.

Однако не следует быть настолько наивными, чтобы полагать, что использование HTMX означает отсутствие необходимости писать JavaScript . Некоторое количество JavaScript все еще может потребоваться для таких вещей, как перетаскивание, диаграммы, средства выбора цвета и даты и т. д. Хотя мы всегда можем использовать независимые от платформы решения, такие как SortableJS и Floating UI. Кроме того, в будущем мы также можем обнаружить меньшую потребность в JavaScript, поскольку веб-стандарты продолжают развиваться с появлением новых элементов HTML, таких как недавний элемент <dialog> .

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

Наконец, создать конечную точку в WordPress не так уж и просто. Рассмотрим плагин Books из предыдущих примеров. Нам нужен путь на сервере, который будет отвечать списком книг в форме HTML. Как нам зарегистрировать эту конечную точку?

  • Обнаружить параметр GET во время действия init или admin_init ?
  • Используете API-интерфейс администратора Ajax?
  • Зарегистрировать конечную точку REST API?
  • Добавить собственное правило перезаписи?

Вариантов много, но ни один из них не делает задачу настолько простой, насколько она должна быть.

ХАТЕОАС

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

Когда мы получаем HTML с сервера, кнопка на странице имеет либо вариант ВКЛ, либо вариант ВЫКЛ. В зависимости от того, какой из них отображается на экране, действие щелчка будет разным.

Из-за этого браузеру не нужно понимать наше приложение. Обычно мы даем понять браузеру, предоставляя код JavaScript для явного программирования всех действий. Теперь у нас есть только HTML, и браузеру не требуется никаких предварительных знаний о том, как ведет себя наше приложение или каково его состояние. Ему просто нужно отобразить на экране HTML-код, который сам кодирует состояние нашего приложения.

Этот тип архитектуры известен как HATEOAS, что означает «Гипермедиа как двигатель состояния приложения». Это специализированный тип архитектуры REST, который использует гипермедиа в качестве среды для передачи состояния, и эта же гипермедиа становится интерфейсом, через который пользователь переводит приложение в новые состояния.

На веб-сайте HTMX есть отличная коллекция статей, эссе и выступлений на эту тему, если вы хотите узнать больше. Для целей этой статьи давайте перейдем к тому, почему HTMX может иметь большое значение для разработчиков WordPress.

HTML <3 WordPress

WordPress — это гигантский монолитный PHP-сервер. Плагины WordPress также в основном написаны на PHP. Они могут добавлять новые функции на сайт, используя API-интерфейсы PHP, предоставляемые WordPress, такие как API-интерфейсы Hooks и API базы данных. Эти API недоступны из JavaScript, поэтому разработчикам плагинов следует хранить как можно большую часть своего кода плагинов на сервере. Если когда-либо и была мотивация использовать HTMX, то это она!

Во многих отношениях HTMX был создан для WordPress. Вернее, для таких приложений , как WordPress; приложения, которые не хотели бы быть обременены иностранным языком, который вынуждает их оставить свои коллекции серверных API. Особенно тогда, когда было бы достаточно простой передачи состояния с помощью гипермедиа.

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

Большие плагины также могут быть особенно интересны. Приложения JavaScript могут расти экспоненциально быстро. HTMX может позволить этим плагинам удалить свои массивные API-интерфейсы JSON и приложения JavaScript и оставить вместо них простой HTML-сервер, который будет иметь полный доступ к API-интерфейсам WordPress.

Последние мысли

Я уже некоторое время экспериментировал с HTMX, используя его с PHP и Go. Он предлагает убедительную альтернативу для создания пользовательских интерфейсов в Интернете и убедительный аргумент в пользу использования гипермедиа для управления состоянием приложения.

Если вы разработчик плагинов, обязательно обратите внимание на HTMX. В этой статье мы лишь прикоснулись к поверхности, а документация очень хорошо написана и содержит множество примеров. Кроме того, он на удивление короткий, учитывая, сколько возможностей HTMX поставляется «из коробки». Вы сможете начать работу с HTMX и PHP за несколько минут.