Полноценная веб-разработка с использованием HTMX и Bun, часть 1: Elysia и MongoDB

автор


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

Технический стек

В этой статье мы сосредоточимся на том, как взаимодействуют четыре основных компонента нашего технологического стека. Компоненты: Bun, HTMX, Elysia и MongoDB. Этот стек обеспечивает быструю настройку, которую легко настроить и легко изменить.

  • Bun — это среда выполнения JavaScript, сборщик пакетов, менеджер пакетов и средство запуска тестов.
  • Elysia — это высокопроизводительный HTTP-сервер, похожий на Express, но созданный для Bun.
  • HTMX предлагает новый подход к добавлению детальной интерактивности в HTML.
  • MongoDB — это флагманское хранилище данных NoSQL, ориентированное на документы.

Обратите внимание, что эта статья состоит из двух частей. Во второй половине мы добавим Pug, шаблонизатор HTMX, который будем использовать для разработки нескольких необычных интерфейсных взаимодействий.

Установка и настройка

Вам нужно будет установить Bun.js, что легко сделать. Мы также собираемся запустить MongoDB как сервис вместе с Bun на нашей машине разработки. Вы можете прочитать об установке и настройке MongoDB здесь. После установки этих пакетов оба bun -v и mongod -version команды должны работать из командной строки.

Далее начнем новый проект:


$ bun create elysia iw-beh

Это говорит bun создать новый проект с использованием шаблона Elysia. А шаблон в Bun — это удобный способ начать проекты с помощью create команда. Bun может работать как Node, без какой-либо настройки, но такую ​​конфигурацию приятно иметь. (Подробнее о шаблонах булочек можно узнать здесь.)

Теперь перейдите в новый каталог: $ cd iw-beh.

И запустите проект как есть: $ bun run src/index.js.

Эта последняя команда сообщает bun запустить src/index.js файл. src/index.js file — это код для запуска простого сервера Elysia:


import { Elysia } from "elysia";

const app = new Elysia()
  .get("https://www.infoworld.com/", () => "Hello Elysia")
  .listen(3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

В этом файле мы импортируем Elysia и используем его для создания экземпляра нового сервера, который прослушивает порт 3000 и имеет один GET конечная точка в корне. Эта конечная точка возвращает текстовую строку: «Привет, Элизия». То, как все это работает, по духу похоже на Express.

Если вы посетите localhost:3000 вы получите простое приветствие:

Простое приветствие, которое гласит: «Привет, Элизия». ИДГ

Теперь, когда у нас работает Elysia, давайте добавим static плагин. У Elysia есть несколько плагинов для обработки распространенных сценариев. В данном случае мы хотим передать некоторый HTML-код с диска. static плагин — это именно то, что нам нужно:


$ bun add @elysiajs/static

Теперь сервер Elysia, на котором работает static плагин должен обслуживать все, что есть в iw-beh/public каталог. Если мы добавим туда простой HTML-файл и посетим localhost:3000/ publicмы увидим его содержимое.

Магия HTMX

Далее давайте добавим HTML-страницу в index.html. Вот простой пример с домашней страницы HTMX:


<script src="https://unpkg.com/htmx.org@1.9.10"></script>

<button hx-post="/clicked"
    hx-trigger="click"
    hx-target="#parent-div"
    hx-swap="outerHTML">
    Click Me!
</button>

На этой странице отображается кнопка. При нажатии на кнопку осуществляется вызов сервера для /clicked конечная точка, и кнопка заменяется тем, что есть в ответе. Там еще ничего нет, поэтому в настоящее время он ничего не делает.

Но обратите внимание, что все это по-прежнему HTML. Мы делаем вызов API и выполняем детальное изменение DOM без использования JavaScript. (Работа выполняется JavaScript в htmx.org библиотеку, которую мы только что импортировали, но дело в том, что нам не нужно об этом беспокоиться.)

HTMX предоставляет синтаксис HTML, который выполняет эти действия, используя всего три атрибута элемента:

  • hx-post отправляет сообщение, когда оно инициируется по запросу AJAX.
  • hx-target рассказывает hx-post какие события выполняют запрос AJAX.
  • hx-swap говорит, что делать, когда происходит событие AJAX. В этом случае замените текущий элемент ответом.

Это довольно просто!

Элизия и MongoDB

Теперь давайте создадим в Elysia конечную точку, которая будет что-то писать в MongoDB. Сначала мы добавим драйвер MongoDB для Bun:


bun add mongodb

Далее измените src.index.ts так:


import { Elysia } from "elysia";
import { staticPlugin } from '@elysiajs/static';
const { MongoClient } = require('mongodb');

const app = new Elysia()
  .get("https://www.infoworld.com/", () => "Hello Elysia")
  .get("/db", async () => {

    const url = "mongodb://127.0.0.1:27017/quote?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.8.0";

    const client = new MongoClient(url, { useUnifiedTopology: true });
try {

    await client.connect();

    const database = client.db('quote');
    const collection = database.collection('quotes');

    const stringData = "Thought is the grandchild of ignorance.";

    const result = await collection.insertOne({"quote":stringData});
    console.log(`String inserted with ID: ${result.insertedId}`);

  } catch (error) {
    console.error(error);
  } finally {
    await client.close();
  }
          return "OK";
  })
  .use(staticPlugin())
  .listen(3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

В этом коде мы добавили /db конечная точка, которая взаимодействует с MongoDB. Прямо сейчас он просто записывает цитату в базу данных котировок внутри коллекции котировок. Вы можете проверить это напрямую, перейдя на localhost:3000/db. Затем вы можете убедиться, что данные находятся в MongoDB:


$ mongosh

test> use quote
switched to db quote
quote> db.quotes.find()
[
  {
    _id: ObjectId("65ba936fd59e9c265cc8c092"),
    quote: 'Thought is the grandchild of ignorance.',
    author: 'Swami Venkatesananda'
  }
]

Создайте таблицу HTML

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


.get("/quotes", async () => {
    const data = [
      { name: 'Alice' },
      { name: 'Bob' },
    ];
    // Build the HTML list structure
  let html="<ul>";
  for (const item of data) {
    html += `<li>${item.name}</li>`;
  }
  html += '</ul>';

    return html
  })

А затем использовать его в нашем index.html:


<ul id="data-list"></ul>
<button hx-get="/quotes" hx-target="#data-list">Load Data</button>

Теперь, когда вы загружаете /public/index.html и нажмите кнопку, отобразится список, отправленный с сервера. Обратите внимание, что выдача HTML из конечной точки отличается от обычного шаблона JSON. Это задумано. Здесь мы соответствуем принципам RESTful. В HTMX есть плагины для работы с конечными точками JSON, но это более идиоматично.

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

Теперь мы можем получить данные из базы данных:


.get("/quotes", async () => {

const url = "mongodb://127.0.0.1:27017/quote?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.8.0";

      const client = new MongoClient(url, { useUnifiedTopology: true });
    try {
      await client.connect();

      const database = client.db('quote');
      const collection = database.collection('quotes');

      const quotes = await collection.find().toArray();

      // Build the HTML table structure
      let html="<table border="1">";
      html += '<tr><th>Quote</th><th>Author</th></tr>';
      for (const quote of quotes) {
        html += `<tr><td>${quote.quote}</td><td>${quote.author}</td></tr>`;
      }
      html += '</table>';

      return html;
    } catch (error) {
      console.error(error);
      return "Error fetching quotes";
    } finally {
      await client.close();
    }

  })

В этой конечной точке мы извлекаем все существующие котировки в базе данных и возвращаем их в виде простой таблицы HTML. (Обратите внимание, что в реальном приложении мы бы извлекли работу по подключению к базе данных в центральное место.)

Вы увидите что-то вроде этого:

Таблица HTML с одной строкой и текстом. ИДГ

На этом снимке экрана показана одна строка, которую мы вставили, когда нажали кнопку /db конечная точка раньше.

Теперь добавим возможность создания новой цитаты. Вот внутренний код (src/index.ts):


app.post("/add-quote", async (req) => {
    const url = "mongodb://127.0.0.1:27017/quote?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.8.0";

    try {
        const client = new MongoClient(url, { useUnifiedTopology: true });
        await client.connect();

        const database = client.db('quote');
        const collection = database.collection('quotes');

        const quote = req.body.quote;
        const author = req.body.author;

        await collection.insertOne({ quote, author });

        return "Quote added successfully";
    } catch (error) {
        console.error(error);
        return "Error adding quote";
    } finally {
        await client.close();
    }
})

А вот и передняя часть(public/index.html):


<form hx-post="/add-quote">
    <input type="text" name="quote" placeholder="Enter quote">
    <input type="text" name="author" placeholder="Enter author">
<button type="submit">Add Quote</button>

Когда вы вводите автора и цитату и нажимаете Добавить цитату он будет добавлен в базу данных. Если вы нажмете Загрузить данные, вы увидите свое обновление в списке. Это должно выглядеть примерно так:

Таблица HTML с двумя строками и текстом. ИДГ

Если вы посмотрите на сервер и клиент приложения, вы увидите, что мы выполняем минимум работы. Самая большая вещь, которую здесь упростил HTMX, — это отправка формы. hx-post Атрибут заменяет всю работу по извлечению данных из формы, их маршалингу в JSON и отправке с помощью fetch() или что-то подобное.

Заключение

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

Самое большое умственное изменение связано с генерацией HTMX с сервера. У вас есть выбор из нескольких высокопроизводительных шаблонизаторов HTML или JavaScript, которые сделают это намного проще. Если вы привыкли работать с HTMX, это не составит труда. По сути, вы исключили из стека весь уровень преобразования JSON.

Мы только что в кратчайшие сроки объединили Bun, Elysia, HTMX и MongoDB, но вы должны хотя бы почувствовать этот стек. Компоненты хорошо работают вместе, без каких-либо ненужных трений. Bun, Elysia и MongoDB спокойно выполняют свою работу, а HTMX требует немного больше внимания, если вы более привыкли к API JSON. Найдите код этой статьи в моем репозитории GitHub. Мы подробнее поработаем с этим примером в следующей статье, где воспользуемся Pug, чтобы добавить в микс несколько необычных взаимодействий.

Дальше читайте это:

  • Почему компании уходят из облака
  • 5 простых способов запустить LLM локально
  • Программирование с помощью ИИ: советы и лучшие практики от разработчиков
  • Знакомьтесь, Zig: современная альтернатива C
  • Что такое генеративный ИИ? Искусственный интеллект, который создает
  • Лучшее программное обеспечение с открытым исходным кодом 2023 года

Related Posts

Оставить комментарий