.
Процесс отправки формы очень похож на отправку якорного тега, за исключением того, что мы можем:
выбрать, какой тип запроса мы хотим выполнить (GET или POST)
прикрепите информацию о пользователе, такую как адрес электронной почты, пароль и т. д., которая будет передана вместе с запросом
Эти два тега являются единственными элементами в чистом HTML, которые могут взаимодействовать с сервером.
А потом появился Javascript.
Изначально JavaScript был создан для добавления простых функций взаимодействия на веб-страницы: проверки форм, получения данных и простой анимации. Но с появлением XMLHttpRequest (позже известного как AJAX) JavaScript превратился в нечто гораздо более мощное и сложное.
Благодаря Javascript разработчики теперь могут инициировать HTTP-запросы без этих двух тегов, используя технологию AJAX. AJAX позволяет извлекать данные с сервера, и хотя XHR может извлекать любые типы данных, включая необработанные HTML-фрагменты, текст или XML, JSON стал фактическим форматом обмена данными.
Это означает, что необходим дополнительный шаг преобразования JSON в HTML с помощью функции, которая визуализирует HTML из JSON. Как показано в примере ниже, мы действуем следующим образом:
извлечение данных JSON из конечных точек /api/users (часть response => response.json())
вставка этих данных в HTML-шаблоны (часть const html)
который затем будет добавлен в DOM (часть document.getElementById())
// Способ JavaScript: преобразование JSON → HTML fetch('/api/users') .then(response => response.json()) .then(users => { const html = users.map(user => `
${user.name}
` ).join(''); document.getElementById('users').innerHTML = html; });
Этот рендеринг подразумевает тесную связь между форматом данных JSON и самой функцией: изменение формата данных JSON может привести к сбою функции рендеринга HTML. Вы уже видите здесь одну потенциальную проблему, и этот момент обычно является точкой трения между фронтенд- и бэкенд-разработчиками: фронтенд-разработчик создаёт пользовательский интерфейс на основе ожидаемого формата JSON, бэкенд-разработчик решает изменить формат, фронтенд-разработчику нужно обновить пользовательский интерфейс, бэкенд-разработчик снова меняет формат, фронтенд-разработчик снова меняет формат и т. д.
По какой-то причине веб-разработчики начали повсеместно использовать JSON и управлять всем с помощью JSON. Это привело к появлению так называемых одностраничных приложений (SPA): в отличие от традиционного HTML 2.0, нам больше не нужно перемещаться между страницами. Весь контент остаётся на одной странице и обновляется с помощью JS и рендеринга пользовательского интерфейса. Именно так работают такие фреймворки, как React, Angular и Vue.js.
«Становящаяся нормой в веб-разработке — создание одностраничных приложений на React с серверным рендерингом. Два ключевых элемента этой архитектуры: – Основной пользовательский интерфейс создается и обновляется на JavaScript с использованием React или чего-то подобного. – Бэкэнд — это API, к которому приложение обращается с запросами. Эта идея буквально захлестнула интернет. Она началась с нескольких крупных популярных сайтов и распространилась на другие сайты, например, на маркетинговые площадки и блоги.
(Том Макрайт, https://macwright.com/2020/05/10/spa-fatigue)
Большинство современных архитектур одностраничных приложений (SPA) представляют собой «клиентские» приложения, где большая часть работы выполняется на стороне клиента, а бэкенд представляет собой лишь API, возвращающий JSON. Такая структура известна своей быстрой и плавной работой, но действительно ли нам нужна такая сложность каждый раз?
«(…) есть также множество задач, для которых я не вижу конкретных преимуществ использования React. Это, например, блоги, сайты с корзинами покупок, сайты, в основном, с CRUD-запросами и формами».
(Том Макрайт, https://macwright.com/2020/05/10/spa-fatigue)
Усталость от Javascript реальна
«Усталость от Javascript» становится всё громче. Она относится к основным недостаткам разработки SPA:
Растущая сложность : библиотеки и фреймворки становятся всё более громоздкими и сложными, требуя для управления ими больших команд. Некоторые узкоспециализированные фреймворки также подразумевают, что разработчикам JavaScript приходится специализироваться на одной технологии. Ни один разработчик Python не называл себя «разработчиком Tensorflow Python». Они просто разработчики Python, и переход с TF на Pytorch по-прежнему означает, что вы можете читать и использовать оба.
Тесная связь : взаимосвязь между API данных и пользовательским интерфейсом создаёт напряжение внутри команд. Критические изменения происходят каждый день, и решить эту проблему невозможно, пока команды используют JSON в качестве интерфейса обмена данными.
Распространение фреймворков : количество фреймворков продолжает расти, что приводит к реальному ощущению «усталости» среди разработчиков JS.
Избыточная инженерия : в 90% случаев вам не нужны фреймворки с большим объёмом JS. А в некоторых случаях (например, для приложений с большим объёмом контента) это даже плохая идея.
За исключением высокоинтерактивных/совместных пользовательских интерфейсов, простого HTML с многостраничными приложениями часто бывает достаточно.
Так что же такое HTMX?
HTMX — это очень лёгкая JS-библиотека (14 КБ), предлагающая HTML-ориентированный подход к созданию динамических веб-приложений. Она расширяет возможности HTML, позволяя любому элементу отправлять AJAX-запросы и обновлять любую часть DOM. В отличие от JS-фреймворков, которые выполняют всю рендеринг на стороне клиента, сервер выполняет основную работу, возвращая HTML-фрагменты для вставки в DOM. Это также означает, что если вы уже знакомы с шаблонизаторами и HTML, обучение будет гораздо проще по сравнению с изучением React или Angular.
Вместо отказа от гипермедиа в пользу JSON API, HTMX расширяет возможности HTML за счет следующих возможностей:
Любой элемент может выполнять HTTP-запросы (не только и
Любой HTTP-метод (GET, POST, PUT, DELETE, PATCH)
Любой элемент может быть объектом обновлений
Любое событие может инициировать запросы (щелчок, отправка, загрузка и т. д.)
Фактически, вы можете написать свой собственный небольшой пользовательский интерфейс в стиле GPT с помощью HTMX и всего нескольких строк Python!
Реальная демонстрация: приложение ChatGPT с HTMX и FastAPI
В этой статье мы создадим небольшой чат, используя менее 100 строк кода Python и HTML. Мы начнём с очень простых демонстраций, чтобы показать, как работает HTMX, затем добавим простой интерфейс чата и возможность потоковой передачи. Чтобы сделать чат ещё привлекательнее, мы воспользуемся набором инструментов Google Agent Development Toolkit, чтобы использовать агентов в нашем чате!
Простые демонстрации HTMX
Предположим, у нас есть API, возвращающий список пользователей. Мы хотим нажать кнопку, чтобы получить данные и отобразить список.
Традиционный способ JS:
Демо
Пользователи
Показать
И вот как это можно сделать с HTMX.
Сначала создайте свой бэкэнд:
из fastapi импорт FastAPI, запрос из fastapi.responses импорт HTMLResponse из fastapi.templating импорт Jinja2Templates импорт запросы app = FastAPI() templates = Jinja2Templates(directory=»templates») @app.get(«/», response_class=HTMLResponse) async def home(request: Request): return templates.TemplateResponse(«demo.html», {«request»: request}) @app.get(«/users») async def get_users(): r = requests.get(«https://dummyjson.com/users») data = r.json() html = «» for row in data['users']: html += f»
{row['firstName']} {row['lastName']}
n» return HTMLResponse(html)
И затем HTML:
Демо
Пользователи
Показать
И вы получаете точно такой же результат! Что только что произошло? Посмотрите на элемент . Мы видим три атрибута, начинающихся с hx-. Зачем они здесь?
hx-get: Нажатие этой кнопки инициирует GET-запрос к конечной точке /users.
hx-target: сообщает браузеру о необходимости заменить содержимое элемента с идентификатором usersList на HTML-данные, полученные с сервера.
hx-swap: сообщает браузеру о необходимости вставить HTML-код внутрь целевого элемента.
Итак, вы уже знаете, как использовать HTML. Преимущество этого способа в том, что если вы решите изменить HTML-код, это ничего не сломает на вашей странице.
Конечно, у использования HTMX есть свои преимущества и недостатки. Но мне, как разработчику Python, очень приятно экспериментировать с бэкендом FastAPI, не особо беспокоясь о рендеринге HTML. Просто добавьте шаблоны Jinja, немного CSS Tailwind, и всё готово!
Наш первый чат с HTMX и FastAPI
Итак, сейчас самое время действовать серьёзно. Для начала мы создадим чат-бота, который будет принимать запрос пользователя и выдавать его в обратном порядке. Для этого мы создадим страницу со следующими функциями:
список сообщений
текстовая область для ввода данных пользователем
И представьте себе, HTMX позаботится об отправке/получении сообщений! Вот как будет выглядеть результат:
Обзор
Поток следующий:
Пользователь вводит запрос в текстовую область
Эта текстовая область заключена в форму, которая отправит POST-запрос на сервер с параметром запроса.
Бэкенд получает запрос и выполняет с ним какие-то действия (в реальной жизни мы можем использовать LLM для ответа на запрос). В нашем случае, для демонстрационных целей, мы просто ответим, возвращая запрос побуквенно.
Бэкэнд оборачивает ответ в HTMLResponse (не JSON!)
В нашей форме HTMX сообщает браузеру, куда вставить ответ, как показано в hx-target, и как поменять его местами с текущим DOM.
Вот и всё. Итак, начнём!
Бэкэнд
Мы определим маршрут /send, который ожидает строку запроса от интерфейса, инвертирует ее и отправляет обратно в теге
.
из fastapi импорт FastAPI, Запрос, Форма из fastapi.templating импорт Jinja2Templates из fastapi.responses импорт HTMLResponse импорт asyncio импорт время app = FastAPI() templates = Jinja2Templates(«templates») @app.get(«/») асинхронный def root(request: Request): return templates.TemplateResponse(request, «simple_chat_sync.html») @app.post(«/send») асинхронный def send_message(request: Request, query: str=Form(…)): message = «».join(list(query)[::-1]) html = f»
» return HTMLResponse(html)
Внешний интерфейс
На стороне frontend мы определяем простую HTML-страницу с использованием Tailwind CSS и HTMX:
Давайте подробнее рассмотрим тег