Image

Усталость от Javascript: HTMX — это всё, что вам нужно для создания ChatGPT. Часть 1

Создание чат-бота (почти) без Javascript, только с использованием Python и HTML.

Делиться

Винтажная информатика

Помню, было время, давным-давно, когда создавать сайты было легко. HTML и CSS. Казалось, всё просто. Сейчас фреймворки Javascript повсюду. Неустанные изменения, растущая сложность. Это явление называется «усталость от Javascript» и связано с тем, что разработчики измотаны погоней за новейшими фреймворками, инструментами разработки, библиотеками и попытками не отставать. С HTMX у разработчиков появился способ создавать увлекательные веб-приложения проще и без выгорания — и без всей этой возни с JavaScript.

Увлекательное веб-приложение, подобное ChatGPT, менее чем в 200 строках кода, на чистом Python и HTML. Например, вот это:

f42fd74418c8581fd6233c5f7e0a3fe3

Краткое напоминание о том, как работал Интернет

Когда Тим Бернерс-Ли создал первую веб-страницу в 1990 году, разработанная им система была преимущественно системой «только для чтения», которая позволяла связывать страницы между собой гиперссылками, которые мы все знаем как анкорные теги в HTML. Таким образом, HTML 1.0 полагался на один-единственный тег и предлагал простую навигацию между страницами.

О нас

Якорный тег — это элемент управления гипермедиа, который выполняет следующий процесс:

  • показать пользователю, что это ссылка (кликабельная)
  • выполнить GET-запрос на URL-адрес гиперссылки

Когда сервер отвечает новой страницей, браузер заменит текущую страницу новой страницей (навигация)

Затем появился Web 2.0, который представил новый тег — тег формы. Этот тег позволял не только читать ресурсы через тег , но и обновлять их. Возможность обновления ресурсов означала, что мы действительно смогли начать создавать веб-приложения. Всё это с помощью всего двух элементов управления:

и .

Процесс отправки формы очень похож на отправку якорного тега, за исключением того, что мы можем:

  • выбрать, какой тип запроса мы хотим выполнить (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 за счет следующих возможностей:

Фактически, вы можете написать свой собственный небольшой пользовательский интерфейс в стиле GPT с помощью HTMX и всего нескольких строк Python!

Реальная демонстрация: приложение ChatGPT с HTMX и FastAPI

В этой статье мы создадим небольшой чат, используя менее 100 строк кода Python и HTML. Мы начнём с очень простых демонстраций, чтобы показать, как работает HTMX, затем добавим простой интерфейс чата и возможность потоковой передачи. Чтобы сделать чат ещё привлекательнее, мы воспользуемся набором инструментов Google Agent Development Toolkit, чтобы использовать агентов в нашем чате!

Простые демонстрации HTMX

Предположим, у нас есть API, возвращающий список пользователей. Мы хотим нажать кнопку, чтобы получить данные и отобразить список.

5385f2b0bad01100eebdabc24a490eaa

Традиционный способ 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:

    Демо

    Пользователи

    И вы получаете точно такой же результат! Что только что произошло? Посмотрите на элемент