译者 | 李睿
审校 | 孙淑娟
HTML作为宇宙的中心
众所周知,全球互联网得以蓬勃发展在很大程度上归功于HTML和CSS。Javascript(JS)可以充当HTML和CSS之间的粘合剂,使页面更具动态性和交互性,但Web编程的历史发展不同。在客户端渲染和其他类似技术出现之后,使用JS创建Web应用程序变得更加困难。
什么是Htmx?
Htmx是一个库,允许用户使用简单的标记创建现代且强大的用户界面。多亏有了它,可以直接从HTML元素执行AJAX请求、触发CSS转换、调用WebSocket和服务器发送的事件。
SSR应用
Htmx的使用促使人们逐渐放弃客户端渲染(CSR),转而支持服务器端渲染(SSR)。服务端渲染(SSR)被认为是最后的手段,只有在需要快速提高性能时才使用。但是,服务端渲染(SSR)可以构建应用程序的整个用户界面。
Htmx不需要任何其他JS包即可运行,并且与框架和语言无关。因此,它可以与任何服务器平台一起使用,例如NodeExpress、RAILS、Django、Phoenix、Laravel等。
重用服务器上的组件
Htmx允许用户使用更熟悉的库重用服务器端用户界面(UI)元素;例如,用于Node的Pug或用于RAILS和Django的模板库。它有助于使HTML变得复杂和动态。
这里是RentalsListing,一个使用Express.js和HTML构建的演示应用程序。它对统计和动态场景使用相同的部分:
HTML
ul.results
each rental in rentals
li
article.rental
button.image(type="button", _="on click toggle .large then if #view-caption.textContent === 'View Larger' then set #view-caption.textContent to 'View Smaller' else set #view-caption.textContent to 'View Larger'")
img(src=rental.attributes.image, alt='An image of ' + rental.attributes.title)
small#view-caption View Larger
.details
h3
a(href='/rentals/' + rental.id) #{rental.attributes.title}
.detail.owner
span Owner:
| #{rental.attributes.owner}
.detail.type
span Type:
| #{rental.attributes.category}
.detail.location
span Location:
| #{rental.attributes.city}
.detail.bedrooms
span Bedrooms:
| #{rental.attributes.bedrooms}
.map
img(alt='A map of ' + rental.attributes.title, src=rental.mapbox, width="150",height="150")
在主页的列表中,使用了Pug库中的include来显示部分内容:
HTML
extends layout
block content
.jumbo
.right
h2 Welcome to Super Rentals!
p We hope you find exactly what you're looking for in a place to stay.
a.button(href="/about") About Us
.rentals
label
span Where would you like to stay?
input.light(type="text", name="search",
hx-post="/search" ,
hx-trigger="keyup changed delay:500ms" ,
hx-target=".results" ,
hx-indicator=".htmx-indicator")
include includes/rental-list.pug
每次用户在网站上搜索租赁房产时,都可以使用相同的部分填充搜索结果。结果如下所示:
JavaScript
app.post('/search', (req, res) => {
const { search } = req.body;
const results = _rentals.data.filter(r => {
const _search = search.toLowerCase();
const _title = r.attributes.title.toLowerCase();
return _title.includes(_search);
});
const template = pug.compileFile('views/includes/rental-list.pug');
const markup = template({ rentals: results });
res.send(markup);
});
服务器端路由
客户端路由带来了一系列问题。例如,在基于散列的路由和基于URL的路由之间总是存在一个两难选择。由于旧版浏览器(如Internet Explorer 11)不支持历史API,因此在URL中使用片段ID的基于哈希的路由几乎总是首选。
大多数JS框架都实现了自己的客户端路由逻辑。同时,所有框架都使用自己的浏览器API,例如window.history。这导致应用程序中出现大量样板代码。
更少的JS代码
Htmx的主要优势在于编写并发送到浏览器的JS代码量。与hyperscript一起,该库允许用户创建丰富的交互式应用程序,而无需使用JS中的客户端代码:
HTML
<!-- have a button POST a click via AJAX -->
<button hx-post="/clicked" hx-swap="outerHTML">
Click Me
</button>
当单页应用刚开始流行时,社区采用JSON作为数据交换的标准。现在,为了从JSON数据中对HTML进行逆向工程,用户通常需要处理通过API来自服务器的大量客户端数据。API响应通常包含不完整或冗余的数据。
为了解决这个问题,已经开发了像GraphQL这样的复杂替代方案,因此用户只能从服务器获取所需的数据。Htmx提供了更好的解决方案:只需将HTML替换为从服务器接收到的HTML响应,而不再需要客户端数据。
不再构建/编译
Htmx的另一个优点是不再采用Web应用程序构建工具。可以改用CDN工具:
HTML
<!-- Load from unpkg -->
<script src="<https://unpkg.com/htmx.org@1.3.3>"></script>
不再构建是Web应用程序开发的全球趋势。一方面,ES模块规范已经被所有浏览器开发者所接受。另一方面,现在有了Skypack、Snowpack和Vite工具,可以与CDN和ESM方法结合使用。所有这些最终将导致客户端JavaScript的构建减少。此外,无需安装数千个npm包并维护复杂的构建配置。
统一代码库
一个应用程序的两个代码库意味着额外的开发挑战。特别是,需要同步更新部署、两次配置构建管道、更新两个库中的框架、维护代码,并从两个源运行测试包。
Htmx允许用户将所有代码组合在一个地方:由于渲染在服务器端进行,因此不需要单独的接口基础。从长远来看,这可以为用户节省大量时间和费用。此外,开发人员可以更加一致地采取行动,他们不必检查两个或更多存储库。
行为原则的局部性(LoB)
LoB原理是由编程理论家Richard Gabriel提出的。他指出,所有开发人员都应该努力确保每段代码的行为在验证时是显而易见的。
Gabriel认为,局部性对于保持代码易于维护至关重要。局部性是一种特性,它允许程序员在看到代码的一小部分后就可以了解代码属于架构的哪一部分。
它看起来像这样:
HTML
The behaviour of a code unit should be as obvious as possible by looking only at that unit of code
<div hx-get="/clicked">Click Me</div>
缺乏状态同步的问题
客户端状态管理产生的问题比解决的问题多。这一原则的实现导致客户端和服务器端都需要状态管理。另一种解决方案是将状态存储在服务器上。在这种情况下,客户端充当虚拟执行器,用于呈现状态更改。
这与瘦客户机模式类似,瘦客户机模式是一种带有连接到终端服务器的轻量级操作系统。这些设备被用来创建第一个用于节省资源的Web应用程序。
Htmx将帮助用户避免混淆状态管理网络中的用户界面(UI)代码;例如,双向数据绑定、单向数据流和反应式数据。
原文标题:Removing JavaScript: How To Use HTML With Htmx and Reduce the Amount of Code,作者:Alexey Shepelev