Использование с Express.js

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

Установка и настройка Express.js

Для начала необходимо установить Express.js. Создайте новый проект и установите зависимости:

mkdir htmx-express
cd htmx-express
npm init -y
npm install express

Затем создайте файл app.js, в котором будет описан сервер на Express:

const express = require('express');
const app = express();
const port = 3000;

app.set('view engine', 'ejs');
app.use(express.static('public'));

app.get('/', (req, res) => {
  res.render('index');
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

Для рендеринга HTML-шаблонов мы будем использовать EJS. Установите его:

npm install ejs

Теперь создайте файл шаблона views/index.ejs, который будет использовать HTMX для выполнения запросов на сервер.

Подключение HTMX

HTMX можно подключить с помощью CDN или локально. Для простоты добавим ссылку на CDN в шаблон index.ejs:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTMX и Express</title>
  <script src="https://unpkg.com/htmx.org@1.7.0"></script>
</head>
<body>
  <div>
    <h1>Добро пожаловать в приложение на HTMX и Express</h1>
    <button hx-get="/message" hx-target="#message" hx-swap="outerHTML">Получить сообщение</button>
    <div id="message"></div>
  </div>
</body>
</html>

В этом примере кнопка выполняет GET-запрос на сервер по адресу /message и заменяет содержимое элемента с ID message на новый HTML-контент, который вернёт сервер.

Обработка запросов с использованием HTMX

Теперь добавим обработчик для маршрута /message на сервере. Он будет генерировать HTML-контент для отображения в элементе #message:

app.get('/message', (req, res) => {
  res.send('<p>Это сообщение было получено с сервера!</p>');
});

Когда пользователь нажимает кнопку, HTMX отправляет запрос на сервер, и содержимое блока #message обновляется новым текстом, полученным от сервера.

Пост-запросы с HTMX

HTMX поддерживает не только GET-запросы, но и POST-запросы. Для этого достаточно указать атрибут hx-post вместо hx-get. Рассмотрим пример формы, которая отправляет данные на сервер с помощью POST-запроса:

<form hx-post="/submit" hx-target="#response" hx-swap="outerHTML">
  <input type="text" name="username" placeholder="Введите имя">
  <button type="submit">Отправить</button>
</form>
<div id="response"></div>

На сервере добавим маршрут для обработки POST-запроса:

app.post('/submit', express.urlencoded({ extended: true }), (req, res) => {
  const username = req.body.username;
  res.send(`<p>Спасибо за отправку, ${username}!</p>`);
});

Когда форма отправляется, данные с поля username передаются на сервер через POST-запрос. Сервер возвращает HTML-контент, который заменяет содержимое блока #response.

Работа с динамическим контентом

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

Допустим, на сервере имеется массив данных:

const data = [
  { id: 1, name: 'Пользователь 1' },
  { id: 2, name: 'Пользователь 2' },
  { id: 3, name: 'Пользователь 3' },
];

На клиенте можно создать кнопку, которая при нажатии будет подгружать этот список с сервера:

<button hx-get="/load-users" hx-target="#users" hx-swap="outerHTML">Загрузить пользователей</button>
<div id="users"></div>

На сервере создадим маршрут, который возвращает этот список:

app.get('/load-users', (req, res) => {
  let usersList = '<ul>';
  data.forEach(user => {
    usersList += `<li>${user.name}</li>`;
  });
  usersList += '</ul>';
  res.send(usersList);
});

Когда пользователь нажимает кнопку, HTMX отправляет GET-запрос на сервер, который возвращает HTML-список пользователей. Этот список затем вставляется в элемент с ID users.

Интерактивность с HTMX и частичные обновления

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

Пример формы для фильтрации списка:

<input type="text" hx-get="/filter" hx-target="#filtered-users" hx-params="*">
<div id="filtered-users"></div>

На сервере маршрут /filter будет фильтровать список данных в зависимости от введённого значения:

app.get('/filter', (req, res) => {
  const query = req.query['filter'];
  const filteredData = data.filter(user => user.name.toLowerCase().includes(query.toLowerCase()));

  let resultList = '<ul>';
  filteredData.forEach(user => {
    resultList += `<li>${user.name}</li>`;
  });
  resultList += '</ul>';

  res.send(resultList);
});

Когда пользователь вводит значение в поле формы, HTMX отправляет GET-запрос с параметром фильтрации. Сервер возвращает отфильтрованный список, который заменяет содержимое элемента с ID filtered-users.

Заключение

Интеграция HTMX с Express.js позволяет значительно упростить разработку динамичных веб-приложений. HTMX предоставляет мощные возможности для обновления части страницы без необходимости в сложных JavaScript-кодах или фронтенд-фреймворках. В сочетании с Express.js этот инструмент открывает новые горизонты для создания эффективных и интерактивных приложений.