使用 HTMX 和 Bun 进行全栈 Web 开发

news2024/11/21 1:38:42

将 HTMX 放在前端,Bun 放在后端,然后将它们与 Elysia 和 MongoDB 连接起来,形成快速便捷的技术栈,使开发 Web 应用程序变得轻而易举。

Bun 和 HTMX 是目前软件领域最有趣的两个事情。 Bun 是一个速度极快的一体化服务器端 JavaScript 平台,而 HTMX 是一种 HTML 扩展,用于创建简单而强大的界面。在本文中,我们将使用这两个出色的工具来开发一个全栈应用程序,该应用程序使用 MongoDB 进行数据存储,并使用 Elysia 作为其 HTTP 服务器。

技术栈

本文的重点是技术栈的四个主要组成部分如何相互作用。这四个组成部分分别是 Bun、HTMX、Elysia 和 MongoDB。这种架构提供了一个快速部署的设置,易于配置并且灵活变化。

  • Bun 是一个 JavaScript 运行时、打包器、包管理器和测试运行器
  • Elysia 是一个高性能 HTTP 服务器,基于 Bun 构建
  • HTMX 提供了一种向 HTML 添加细粒度交互性的新颖方法
  • MongoDB 是旗舰级 NoSQL 面向文档的数据存储

请注意,本文有两个部分。后续我们将合并 Pug、HTMX 模板引擎,用它来开发一些奇特的前端交互。

安装和设置

您需要安装 Bun.js,这很容易做到。我们还将在我们的开发机器上将 MongoDB 作为服务与 Bun 一起运行。安装这些软件包后,bun -vmongod -version 命令都可以在命令行中运行。

接下来,让我们开始一个新项目:

bun create elysia iw-beh

这告诉 bun 使用 Elysia 模板创建一个新项目。 Bun 中的模板是使用 create 命令快速启动项目的便捷方法。Bun 可以像 Node.js 一样工作,无需任何配置。

现在,进入新目录 cd iw-beh,并按原样运行项目 bun run src/index.js

最后一个命令告诉 bun 运行 src/index.js 文件。src/index.js 文件是启动 Elysia 服务器的代码:

import { Elysia } from "elysia";

const app = new Elysia()
  .get("/", () => "Hello Elysia")
  .listen(3000);

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

在此文件中,我们导入 Elysia 并使用它实例化一个新服务器,该服务器侦听端口 3000 并在根目录下有一个 GET 端点。该端点返回一个文本字符串「Hello Elysia」,其工作原理与 Express 的相似。如果您访问 localhost:3000,您会收到一条简单的问候语。

现在我们已经运行了 Elysia,让我们添加 static 插件。 Elysia 有几个用于处理常见场景的插件。在本例中,我们希望从磁盘提供一些 HTML。 static 插件正是我们所需要的:

bun add @elysiajs/static

现在,运行 static 插件的 Elysia 服务器应该提供 iw-beh/public 目录中的所有内容。如果我们在其中放置一个简单的 HTML 文件并访问 localhost:3000/public,我们将看到它的内容。

HTMX 的魔力

接下来,让我们向 index.html 添加一个 HTMX 页面。这是 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。这项工作是由我们刚刚导入的 htmx.org 库中的 JavaScript 完成的,但重点是我们不必担心它。

HTMX 提供了一种 HTML 语法,只需使用三个元素属性即可完成这些操作:

  • hx-post 在 AJAX 请求触发时提交帖子
  • hx-target 告诉 hx-post 哪些事件执行 AJAX 请求
  • hx-swap 表示 AJAX 事件发生时要做什么

Elysia 和 MongoDB

现在让我们在 Elysia 中创建一个端点,它将向 MongoDB 写入一些内容。首先我们将为 Bun 添加 MongoDB 驱动程序:bun add mongodb

接下来,像这样修改 src/index.ts

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

const app = new Elysia()
  .get('/', () => '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 通信。现在它只是将一条引用写入到 quote 数据库中的 quotes 集合内。您可以直接通过访问 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'
  }
]

创建 HTMX 表格

现在我们从前端连接到数据库,让我们创建一个表来输出现有的报价。作为快速测试,我们将向服务器添加一个端点:

.get("/quotes", async () => {
  const data = [{ name: 'Alice' }, { name: 'Bob' }]
  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 框架来使事情更易于管理。

现在,我们可以从数据库中检索数据:

.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 表返回。在实际应用程序中,我们会将数据库连接工作提取到一个中心位置。

如果您查看到目前为止应用程序的服务器和客户端,您会发现我们只做了最少的工作。HTMX 在这里简化的最重要的事情是提交表单。hx-post 属性取代了从表单中取出数据、将其编组为 JSON 并使用 fetch() 或类似内容提交的所有工作。

总结

随着事情变得越来越复杂,我们开始不得不依赖客户端中的 JavaScript,即使使用 HTMX。例如,内联行编辑。我们可能希望使用 JavaScript 执行的某些操作(例如将新行直接插入表中)可以通过 HTMX 交换来完成。HTMX 允许您使用简单的语法做很多事情,然后在必要时回退到 JavaScript。

最大的心理变化是从服务器生成 HTMX。您可以选择多种 HTML 或 JavaScript 模板引擎,使这一切变得更加容易。一旦我们习惯使用 HTMX,一切都会变得轻而易举。本质上我们已经从技术栈中消除了整个 JSON 转换层。

我们刚刚通过组合 Bun、Elysia、HTMX 和 MongoDB 进行了简单的演示模版,但您至少应该对这个技术栈有一个感觉,这些组件可以很好地协同工作。Bun、Elysia 和 MongoDB 安静地完成自己的工作,而如果您更习惯 JSON API,则 HTMX 需要多考虑一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1570096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot快速入门笔记(3)

文章目录 一、MybatisPlus1、ORM2、添加依赖3、全局配置4、Navicat5、UserController6、CRUD操作7、BaseMapper8、两个注解 二、多表查询1、模拟用户订单2、通过用户查相关订单3、UserMapperNew4、查询订单和所属用户5、OrderMapper6、OrderController 三、条件查询四、分页查询…

爬虫 新闻网站 并存储到CSV文件 以红网为例 V2.0 (控制台版)升级自定义查询关键词、时间段,详细注释

爬虫&#xff1a;红网网站&#xff0c; 获取指定关键词与指定时间范围内的新闻&#xff0c;并存储到CSV文件 V2.0&#xff08;控制台版&#xff09; 爬取目的&#xff1a;为了获取某一地区更全面的在红网已发布的宣传新闻稿&#xff0c;同时也让自己的工作更便捷 对比V1.0升级的…

瑞吉外卖实战学习--14、菜品上传

添加菜品接口 前言效果图1、菜品分类查询接口2、上传图片和下载图片3、创建接收数据的Dto4、创建提交的方法 前言 本项目gitee位置&#xff1a;gitee网址 本篇文章是学习了添加菜品的总结&#xff0c;其中包括菜品分类的接口&#xff0c;图片上传接口&#xff0c;数据整体上传…

【Spring篇】Spring IoC DI

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring系列】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 前言一、IoC二、…

语义分割——自动驾驶鱼眼数据集

一、重要性及意义 环境感知&#xff1a;语义分割技术能够精确识别道路、车辆、行人、障碍物、交通标志和信号等各种交通场景元素。这为自动驾驶系统提供了丰富的环境信息&#xff0c;有助于车辆准确理解周围环境的结构和动态变化。决策规划&#xff1a;基于语义分割的结果&…

AI Kimi:帮助教师做好试卷命题

原文&#xff1a;https://www.toutiao.com/article/7353661304307778083/?log_fromcfd0a50014034_1712243146922 最近&#xff0c;Kimichat工具很火。这款软件不仅仅是一个聊天和阅读工具&#xff0c;还是一个强大的教学辅助工具。作为一位教师&#xff0c;尝试使用Kimichat&…

【React】useState为何返回数组而非对象

useState的正确语法如下 const [count, setCount] useState(0)通过打印可以看到useState返回一个数组&#xff0c;那么为何不返回对象呢 涉及到数组与对象间解构方式的差异 数组的解构&#xff1a;根据索引 const [a,,b] [1,2,3] console.log(a) // 1 console.log(b) // 3…

蓝桥集训之垒骰子

蓝桥集训之垒骰子 核心思想&#xff1a;矩阵乘法 f[i]存顶面数值 构造a矩阵 使得*f[i] f[i-1]a 则f[i] f[1] * an 快速幂优化 #include <iostream>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int N 6,m…

xilinx AXI CAN驱动开发

CAN收发方案有很多&#xff0c;常见的解决方案通过是采用CAN收发芯片&#xff0c;例如最常用的SJA1000,xilinx直接将CAN协议栈用纯逻辑实现&#xff0c;AXI CAN是其中一种&#xff1b; 通过这种方式硬件上只需外接一个PHY芯片即可 上图加了一个电平转换芯片 软件设计方面&…

Unity:2D SpriteShape

1.1 简介 Sprite Shape 可以很灵活的更改sprite的轮廓。比如&#xff1a; 它由两部分组成&#xff1a;Sprite Shape Profile、Sprite Shape Controller&#xff0c;需要导入2D Sprite Shape Package. 1.1.1 Sprite导入要求 Texture Type - ‘Sprite (2D and UI)’.Sprite Mo…

【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现

目录 &#x1f31e;一、实验目的 &#x1f31e;二、实验准备 &#x1f31e;三、实验内容 &#x1f33c;1. 认识RMSProp算法 &#x1f33c;2. 在optimizer_compare_naive.py中加入RMSProp &#x1f33c;3. 在optimizer_compare_mnist.py中加入RMSProp &#x1f33c;4. 问…

C#/WPF Inno Setup打包程序

Inno Setup介绍 Inno Setup 是一个免费的 Windows 安装程序制作软件。第一次发表是在 1997 年&#xff0c;现在已经更新到Inno Setup 6了。Inno Setup是一个十分简单实用的打包小工具&#xff0c;可以按照我们自己的意愿设置功能&#xff0c;稳定性也很好。 官方网址&#xff1…

考研人千万不能犯的错误——什么情况下求极限可以直接带入值?

博主最近在复习考研的过程中&#xff0c;做了武忠祥老师的每日一题发现有一个题型错的很集中&#xff0c;就是关于极限数值带入的问题&#xff0c;相信也有不少的宝子容易在这种题型上犯错&#xff0c;今天带大家梳理总结一下常见的计算极限时容易犯的错误 极限的四则运算定义…

harmonyOS安装ohpm

下载 下载地址 HUAWEI DevEco Studio和SDK下载和升级 | 华为开发者联盟 初始化 注意&#xff1a;初始化ohpm前&#xff0c;需先完成node.js环境变量配置 1.解压文件&#xff0c;进入commandline-tools-windows-2.0.0.2\command-line-tools\ohpm\bin 2.执行&#xff1a; init.ba…

第二十三章 Git

一、Git Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布式版…

设计模式总结-建造者模式

建造者模式 模式动机模式定义模式结构模式分析建造者模式实例与解析实例&#xff1a;KFC套餐 模式动机 无论是在现实世界中还是在软件系统中&#xff0c;都存在一些复杂的对象&#xff0c;它们拥有多个组成部分&#xff0c;如汽车&#xff0c;它包括车轮、方向盘、发送机等各种…

点亮创意:ChatGPT如何搭桥DALL-E图像编辑新纪元

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

力扣爆刷第111天之CodeTop100五连刷41-45

力扣爆刷第111天之CodeTop100五连刷41-45 文章目录 力扣爆刷第111天之CodeTop100五连刷41-45一、232. 用栈实现队列二、4. 寻找两个正序数组的中位数三、31. 下一个排列四、69. x 的平方根五、8. 字符串转换整数 (atoi) 一、232. 用栈实现队列 题目链接&#xff1a;https://le…

Kubernetes(k8s):精通 Pod 操作的关键命令

Kubernetes&#xff08;k8s&#xff09;&#xff1a;精通 Pod 操作的关键命令 1、查看 Pod 列表2、 查看 Pod 的详细信息3、创建 Pod4、删除 Pod5、获取 Pod 日志6、进入 Pod 执行命令7、暂停和启动 Pod8、改变 Pod 副本数量9、查看当前部署中使用的镜像版本10、滚动更新 Pod11…

【Unity灶台】食品加工系统模型搭建

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…