HTMX pode ser um grande negócio para WordPress
Publicados: 2024-05-10Construir uma experiência de usuário rica no navegador pode ser uma tarefa desafiadora, que geralmente requer uma quantidade significativa de código JavaScript. À medida que as necessidades e ambições da nossa aplicação aumentam, também aumenta a complexidade do nosso código JavaScript. Portanto, não é nenhuma surpresa a frequência com que os desenvolvedores revisam a forma como pensamos e escrevemos aplicativos JavaScript.
Dias desde a última estrutura JS.
Os desenvolvedores de plug-ins do WordPress estão em situação pior. O ambiente que visamos não é um servidor que controlamos, nem um com controle total sobre toda a página. Embora seja muito possível usar uma estrutura JavaScript com sucesso em um plugin do WordPress, também pode ser extremamente fácil terminar com um projeto cuja escala e complexidade estão além do que você pretendia ou esperava.
Mas e se não precisasse ser assim? Neste artigo, exploraremos como UIs da web modernas são construídas com JavaScript, as dificuldades que os desenvolvedores enfrentam e a alternativa oferecida pelo HTMX. Em particular, veremos por que HTMX e WordPress podem ser uma combinação perfeita.
Como chegamos aqui
Antes do JavaScript, os navegadores eram basicamente apenas leitores de documentos glorificados. Como tal, a maioria das experiências na web eram 'aplicativos de várias páginas' ou, abreviadamente, MPAs. MPAs são aplicações web que consistem em vários documentos HTML, um para cada página da aplicação. À medida que o usuário utiliza o aplicativo, são mostrados diferentes documentos com diferentes ações disponíveis.
As AMPs são muito simples de construir. A navegação é feita usando tags <a>
para vincular a outros documentos, e a entrada do usuário pode ser capturada com um elemento <form>
. O servidor responde às solicitações de links e formulários com novos documentos HTML, substituindo a página que está sendo mostrada na tela.
Um bom exemplo de MPA com o qual você provavelmente está familiarizado é o WP Admin. Cada página de administração é um documento HTML gerado pelo código PHP do WordPress que está sendo executado no servidor. A maioria das páginas do WP Admin, como as páginas de configurações do WordPress, tendem a ser compostas principalmente de formulários que você, usuário, pode enviar.
Por outro lado, um aplicativo de página única, ou SPA, é um aplicativo que usa uma única página HTML. A navegação e a entrada do usuário são então tratadas pelo código JavaScript, alterando dinamicamente partes da página no local, sem a necessidade de trocar a página inteira ou atualizá-la. Isso resulta em uma experiência de usuário mais suave e responsiva.
Atualmente, muitos aplicativos da web usam SPAs como interface da web. Na RebelCode, construímos SPAs para as interfaces administrativas de nossos dois principais plug-ins do WordPress: Spotlight e Aggregator. O editor de sites relativamente novo no WordPress também é um SPA, assim como o editor de postagens baseado em blocos.
O preço que pagamos
SPAs são aplicativos próprios, escritos em JavaScript e executados no navegador. A sua própria definição é também a sua maior ressalva: eles não têm acesso imediato aos recursos do servidor. Isso significa que precisamos estabelecer um canal de comunicação entre o SPA e o servidor.
Vamos criar um plugin WordPress simples para usar um exemplo. Este plug-in fornece
uma interface de usuário CRUD simples para gerenciar livros. A API interna do plugin no servidor pode ser semelhante a esta:
<?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;
Para criar nossa interface SPA moderna, usaremos uma estrutura JavaScript como React; a estrutura JavaScript mais popular que também é usada pelo WordPress. Vamos começar adicionando uma página de administração:
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
Nossa página renderizará um único elemento <div>
vazio que servirá como raiz de nosso aplicativo React, onde o resto da UI será renderizado.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
Então, como listamos os livros armazenados no banco de dados? O código para fazer isso está no servidor, então precisamos de uma maneira de chamá-lo e obter o resultado.
Para fazer isso, podemos expor uma API JSON do servidor. O aplicativo React pode então fazer uma solicitação na URL da nossa API, receber os livros no formato JSON e renderizar a lista. Para este exemplo, vamos supor que adicionamos um endpoint à API REST do 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", }, ] }
Podemos então escrever um componente React que busca os livros e os renderiza como uma lista:
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> ); }
Mas esta solução é muito ingênua e proporciona uma experiência de usuário difícil. Ele não atende a alterações de estado após a desmontagem do componente, armazenando a resposta em cache, repetindo consultas com falha ou evitando que o estado obsoleto substitua o estado mais recente. Na verdade, a maneira como usamos fetch()
em um efeito React geralmente é desencorajada.
Em muitos aspectos, isto pode ser pior do que uma AMP tradicional. Então, para fazer isso corretamente, precisaremos implementar mais algumas coisas em nosso cliente. Ou, de forma mais realista, use pacotes de terceiros.
Mas tudo isso está começando a parecer um esforço desproporcional apenas para criar uma lista de livros. Precisamos realmente criar um aplicativo JavaScript e uma API JSON para criar uma experiência de usuário tranquila?
Vamos contrastar isso com um MPA, onde a renderização da lista de livros pode ser realizada em apenas algumas linhas de código PHP, sem quaisquer dependências:
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
Mas é claro que esta não é uma comparação justa. Esta lista de livros é apenas HTML estático; não é reativo às mudanças de estado ou à entrada do usuário.
Se quisermos ter uma experiência semelhante ao SPA e ao mesmo tempo renderizar o HTML no servidor, onde nosso código tem acesso imediato ao banco de dados, precisaremos encontrar uma maneira de fazer com que o HTML renderizado pelo servidor chegue ao navegador e substitua a lista anterior de livros. Mas conseguir isso sem qualquer código JavaScript é atualmente impossível, então teríamos que aguentar e usar JavaScript de qualquer maneira.
Mas não precisamos escrevê-lo nós mesmos.
Apresentando HTML
HTMX é uma pequena biblioteca JavaScript que faz principalmente uma coisa: permitir que o HTML solicite novo HTML do servidor. Ele faz isso usando novos atributos, que nos permitem dizer ao HTMX de onde obter o novo HTML, com o que trocá-lo e o que aciona a troca. Ele atua como uma ponte entre nosso servidor HTML e a página no navegador.
Esta é uma maneira muito diferente de pensar sobre SPAs, já que não estamos construindo um aplicativo cliente JavaScript para atualizar a página atual. Em vez disso, simplesmente adicionamos alguns atributos HTML para informar ao HTMX como queremos que a página mude quando determinados eventos acontecem.
Mesmo sem o HTMX, você já pode alterar o que é mostrado na tela usando apenas HTML, ainda que de forma bastante limitada. Você já está familiarizado com este recurso HTML: o humilde elemento de link <a>
.
<a href="https://my-wp-site.com/books">View books</a>
Um elemento link fornece ao navegador todas as informações necessárias para realizar a navegação. Ao ser clicado, o navegador pega o href
do elemento, faz uma solicitação naquela URL, baixa a resposta e, supondo que continha HTML, substitui o conteúdo da página pelo novo HTML.
O elemento <form>
é outro exemplo de como o HTML pode solicitar novo HTML.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
Desta vez, o navegador coleta os valores de todas as entradas do formulário, envia-os ao servidor, baixa a resposta e a renderiza na tela.
Por que apenas
Do leia-me do GitHub do HTMX<a>
e<form>
deveriam poder fazer solicitações HTTP? Por que você só deveria poder substituir a tela inteira ?
Bem, o HTMX muda isso.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
Com o atributo HTMX hx-target
, clicar no link agora colocará a resposta de https://my-wp-site.com/books
dentro do elemento com o ID "books"
. É claro que incorporar uma página dentro de outra não é o objetivo aqui. Nosso servidor não precisa responder com a página inteira e pode apenas responder com um fragmento HTML.
Ao expor fragmentos HTML do nosso servidor e dizer ao HTMX como, de onde e quando obter esses fragmentos, podemos criar uma aplicação web semelhante a um SPA sem qualquer JavaScript, onde o servidor tem controle total. De certa forma, o HTML se tornou nosso novo JSON.
E tudo o que precisamos fazer é carregar o script HTMX em nossa página:
<script src="https://unpkg.com/[email protected]"></script>
(Certifique-se de verificar a documentação HTMX para obter instruções, pois o código acima pode estar desatualizado).
Vejamos outro exemplo:
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
Há muito mais acontecendo aqui, então vamos detalhar:
-
hx-get
especifica o URL para enviar uma solicitaçãoGET
quando o botão é clicado. -
hx-target="this"
diz ao HTMX para trocar o botão clicado pela resposta. -
hx-swap="outerHTML"
diz ao HTMX para trocar o botão inteiro, não apenas o que está dentro dele.
Todos juntos, isso diz ao HTMX:
Quando o botão for clicado, envie uma solicitação GET para
/button/off
e substitua esse botão pela resposta.
Digamos que o servidor responda a /button/off
com o HTML abaixo:
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
Você consegue ver a diferença? O atributo hx-get
agora aponta para /button/on
e o texto dentro do botão agora é “Turn on”. Quando este botão é clicado, ele também será substituído pela resposta de /button/on
. Como você pode imaginar, podemos fazer com que o servidor responda com o botão original para completar nossa alternância!
Essa ideia simples de permitir que qualquer elemento solicite novo HTML do servidor e decida para onde esse HTML vai acaba sendo bastante poderosa. Podemos criar guias, pesquisar com resultados ao vivo, barras de progresso e muito mais.
Prós e contras
Ao contrário da maioria das estruturas JavaScript, o HTMX não exige que o código do aplicativo cliente seja compilado e empacotado. Só isso já é um enorme benefício; Os sistemas de construção JavaScript podem ser notoriamente difíceis de configurar e manter, especialmente quando você começa a introduzir recursos e bibliotecas mais exóticas, como TypeScript, JSX, pré-processadores CSS, etc. um ou mais membros dedicados a esta tarefa.
Outro benefício óbvio é a falta de um aplicativo cliente separado. Como tudo o que precisamos é de um servidor HTTP que responda com HTML, podemos usar qualquer linguagem de programação que desejarmos. Este pode ser um grande argumento de venda para você se sua equipe não estiver familiarizada com JavaScript moderno ou não for grande o suficiente para justificar a construção de dois aplicativos. Pode ser especialmente tentador se você for um desenvolvedor de plugins para WordPress, já que você pode usar PHP para todos os aspectos do seu plugin.
Mas talvez o benefício mais importante seja que você não precisa mais de uma API entre o back-end e o front-end do seu aplicativo. Isso pode economizar muito tempo de desenvolvimento, bem como reduzir a quantidade de código que pode produzir bugs, o que também economiza tempo a longo prazo.
Entretanto, não devemos ser tão ingênuos a ponto de assumir que usar HTMX significa não ter que escrever nenhum JavaScript. Alguma quantidade de JavaScript ainda pode ser necessária para coisas como arrastar e soltar, gráficos, seletores de cores e datas e assim por diante. Embora sempre possamos usar soluções independentes de estrutura, como SortableJS e Floating UI. Além disso, também poderemos encontrar menos necessidade de JavaScript no futuro, à medida que os padrões da web continuarem a evoluir com novos elementos HTML, como o recente elemento <dialog>
.
Em segundo lugar, o PHP ironicamente não é muito bom em templates HTML, apesar de ter sido construído para fazer exatamente isso. Sua sintaxe de tag é excessivamente detalhada e sua sintaxe de string HEREDOC tem suporte limitado para interpolação de string.
Por último, criar um endpoint no WordPress não é muito simples. Considere o plugin de livros dos exemplos anteriores. Precisamos ter um caminho no servidor que responda com a lista de livros em formato HTML. Como registramos esse endpoint?
- Detectar um parâmetro GET durante a ação
init
ouadmin_init
? - Usar a API Admin Ajax?
- Registrar um endpoint da API REST?
- Adicionar uma regra de reescrita personalizada?
Existem muitas opções, mas nenhuma torna tudo tão simples quanto deveria ser.
ÓDIO
Há um detalhe sutil em nosso exemplo anterior que é muito fácil de passar despercebido e provavelmente parecerá óbvio depois de apontado.
Quando obtemos o HTML do servidor, o botão na página é a variante ON ou a variante OFF. Dependendo de qual deles é mostrado na tela, a ação do clique será diferente.
Por causa disso, o navegador não precisa entender nossa aplicação. Normalmente faríamos o navegador entender, fornecendo código JavaScript para programar explicitamente todos os comportamentos. Agora só temos HTML, e o navegador não precisa de conhecimento prévio de como nossa aplicação se comporta ou qual é o seu estado. Basta renderizar o HTML na tela, que por sua vez codifica o estado de nossa aplicação.
Este tipo de arquitetura é conhecido como HATEOAS, que significa 'Hypermedia As The Engine Of Application State'. É um tipo especializado de arquitetura REST que usa hipermídia como meio para transferência de estado, e essa mesma hipermídia se torna a interface através da qual o usuário conduz o aplicativo para novos estados.
O site HTMX possui um grande acervo de artigos, ensaios e palestras sobre o assunto, caso você tenha interesse em aprender mais. Para os fins deste artigo, vamos ver por que o HTMX pode ser um grande negócio para os desenvolvedores do WordPress.
HTML <3 WordPress
WordPress é um servidor PHP gigante e monolítico. Os plug-ins do WordPress também são escritos principalmente em PHP. Eles podem adicionar novas funcionalidades ao site usando APIs PHP fornecidas pelo WordPress, como a API Hooks e a API do banco de dados. Essas APIs não estão disponíveis em JavaScript, portanto, os desenvolvedores de plug-ins devem querer manter o máximo possível de seu código de plug-in no servidor. Se alguma vez houve uma motivação para usar HTMX, é essa!
De muitas maneiras, o HTMX foi desenvolvido para WordPress. Ou melhor, para aplicações como WordPress; aplicativos que preferem não ser sobrecarregados com um idioma estrangeiro que os força a deixar para trás suas coleções de APIs de servidor. Especialmente quando a simples transferência de estado usando hipermídia seria suficiente.
Facilitar a criação de boas UIs para plug-ins do WordPress pode ter um impacto dramático no ecossistema de plug-ins. Os desenvolvedores que mantêm plug-ins gratuitos podem achar mais viável criar melhores experiências de usuário para seus usuários, e equipes menores podem ser capazes de iterar mais rapidamente os recursos com o tempo economizado. Isso pode ajudar a tornar plug-ins menores mais competitivos em um mercado fortemente dominado por grandes equipes com orçamentos ainda maiores.
Plug-ins maiores também podem ser especialmente interessantes. Os aplicativos JavaScript podem crescer exponencialmente rápido. O HTMX poderia permitir que esses plug-ins removessem suas enormes APIs JSON e aplicativos JavaScript e deixassem um servidor HTML enxuto em seu lugar com acesso total às APIs do WordPress.
Pensamentos finais
Já faz algum tempo que brinco com HTMX, usando-o com PHP e Go. Ele oferece uma alternativa atraente para a construção de interfaces de usuário na Web e um argumento convincente para o uso de hipermídia para impulsionar o estado do aplicativo.
Se você é um desenvolvedor de plugins, não deixe de conferir o HTMX. Mal arranhamos a superfície neste artigo, e a documentação está muito bem escrita com muitos exemplos. Também é surpreendentemente curto, considerando a quantidade de HTMX que vem pronto para uso. Você poderá começar a usar HTML e PHP em alguns minutos.