معرفی مقدماتی کتابخانه ی HTMX و استفاده های آن

معرفی مقدماتی HTMX

تاریخ انتشار: ۷ ماه پیش

آخرین ویرایش: ۷ ماه پیش

سطح مقاله: مبتدی

دسته:HTMXFrontend

بازدید: ...

مشاهده ی عناوین مهم این مقاله ساختار و سرتیتر های مقاله:

برای مطالعه ی این مقاله باید با مفاهیم ساده ی برنامه نویسی وب مثل HTML و جاوا اسکریپت آشنا باشید.

اگر با مهارت خارق العاده تون الگوریتم یک ماشین زمان رو می نوشتید و توی کدهاتون time.travel().to(2010) رو اجرا می کردید انتظار داشتید از دنیای برنامه نویسی وب چی ببینید؟ با هم کنار jQuery و PHP خوش و خرم بودیم تا اینکه جاوا اسکریپت پر رو بازی در آورد و اومد سمت سرور! زمانی که پای جاوا اسکریپت به سمت سرور هامون باز شد کم کم هیچ تپه ای رو فتح نکرده باقی نذاشت و به قول قانون اتوود (Atwood's Law) که آقای جف اتوود در سال ۲۰۰۷ گفت:‌ «هر چیزی که قابلیت نوشته شدن با جاوا اسکریپت رو داشته باشه، در نهایت با جاوا اسکریپت نوشته خواهد شد!» این قانون از سال ۲۰۰۷ به این طرف فقط قوی تر شده و تکنولوژی های باورنکردنی با جاوا اسکریپت ساخته شده که در اون سال ها حتی تصورش هم سخت بود.

 

نحوه ی کار دنیای وب در اون سال ها به طور غالب استفاده از PHP یا Ruby یا زبان های اینچنینی بود که محتوای شما رو سمت سرور بررسی می کردن و بر اساس دستورات شما یک صفحه ی HTML نهایی رو می ساختن و تحویل کاربر می دادن. به این روش SSR یا Server Side Rendering (رندر سمت سرور) گفته میشه. البته چند سال بعد، حدود سال ۲۰۱۵، شرکت فیسبوک یا متا اولین کنفرانس خودش رو راجع به react برگزار کرد و کم کم سر و صدای زیادی به پا کرد. در واقع react بار پردازشی ساخت صفحات HTML رو از روی دوش سرور برمی داشت و تنها کاری که سرور باید انجام می داد پردازش داده های خام و ارسال اونها به فرانت اند بود تا react با استفاده از جاوا اسکریپت و روی دستگاه کاربر (مثلا موبایل کاربر به جای سرور ما) صفحه رو ساخته و تحویل ما می داد که به اون CSR یا  Client Side Rendering (رندر سمت کلاینت) میگن.

 

طی اون سال ها ترند این شده بود که اگر از CSR استفاده نکنی  اُمُل حساب میشی و باید بری قالب وردپرس طراحی کنی (عزیزان وردپرسی ناراحت نشید!). چند سال گذشت و طبق رسم همیشگی دنیای جاوا اسکریپت، جامعه ی آماری جاوا اسکریپت دوباره به SSR علاقه پیدا کرد! چرا؟ چون ابزار هایی مثل Nuxt و Next.js و Remix و غیره به وجود اومدن که از همین فریم ورک های جاوا اسکریپتی مثل React یا Vue استفاده می کردن اما صفحاتشون رو سمت سرور می ساختن که بازم می شد SSR! و اسم خودشونم گذاشتن meta framework یعنی فریم ورک هایی که روی فریم ورک سوارن! البته تیم react هنوز بیخیال نشده و با جدیت گیر میدن که کتابخونه هستن و فریم ورک حساب نمیشن. بعضی وقتا فکر می کنم برنامه نویس های وب مثل کلاغ می‌مونن که دنبال چیزای براق و جدید میرن، اونم به صورت گله ای! (بلا نسبت شما خواننده ی عزیز که ترافیک سایت رو بالا می برید ☕). 

 

حالا این همه گفتیم که چی؟ می خوام بگم یه دور شمسی قمری زدیم و برگشتیم به SSR اما خب جاوا اسکریپتم دوست داریم اما اونقدرم بی غیرت نشدیم که با جاوا اسکریپت کد بنویسیم برای همین HTML و جاوا اسکریپت رو توی آغل مجبور به جفت گیری می کنیم تا HTMX ساخته بشه!

HTMX آغل زاده ای هست که خدمتتون عرض کردم، روش عجیب و غریبی برای نوشتن کد با جاوا اسکریپت به شکلی که معلوم نباشه با جاوا اسکریپت نوشته شده! HTMX به شما اجازه می ده قابلیت های مدرن و جدید جاوا اسکریپت رو (در ظاهر) روی اِلمان (element) های HTML دریافت کنید. به کد زیر توجه کنید:

<a href="/about-us">درباره ی ما</a>

این کد یک لینک ساده ی HTML هست اما تا حالا فکر کردین دقیقا وقتی روی لینکی کلیک می کنید چه اتفاقی می افته؟ مرورگر ها هر چی باشن (کروم یا فایرفاکس یا اوپرا و غیره) یه سری قوانین ثابت و مشخصی دارن و همشون ازشون پیروی می کنن حتی با اینکه engine هاشون متفاوته. مثلا بخش جاوا اسکریپتی این قوانین رو ECMAScript تعیین می کنه. وقتی شما روی یک لینک کلیک می کنید مرورگر میدونه که باید یک درخواست GET به آدرس /about-us ارسال کنه. حالا نمیشه همین رفتار رو گسترش داد تا شامل قابلیت های بیشتری بشه؟

<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML"
>
روی من کلیک کن!
</button>

این کد HTMX هست. با «کلیک» روی دکمه ی بالا به مرورگر می‌گین یک درخواست «POST» به «آدرس» /clicked ارسال کن و نتیجه اش که همون پاسخ سرور هست رو به عنوان «outerHTML» المانی قرار بده که آیدی parent-div داره!  فهمیدید چطور شد؟ انگار HTML چند ماه دوره بوده و فقط تستسرون تزریق کرده و حالا شده HTMX!

نکته ی مهم

نکــــــته!

برای جلوگیری از به وجود اومدن تداخلات احتمالی بین HTMX و سایر کتابخونه ها و همچنین اتریبیوت (attribute) های شخصی خودتون، می تونید به تمام دستورات HTMX پیشوند data- رو هم اضافه کنید. به طور مثال <a hx-post="/click">دریافت داده ها</a> و <a data-hx-post="/click">دریافت داده ها</a> هر دو صحیح هستن.

در این بخش می خوام به صورت خلاصه وار به کلیدی ترین ویژگی های HTMX اشاره ای داشته باشم چرا که درک این ویژگی ها فلسفه ی کلی این کتابخونه رو براتون توضیح می ده و با پوست و خونتون درک می کنید توسعه دهنده های HTMX از جون ما جاوا اسکریپت نویس ها چی می خوان.

ما دو تا پارادایم اصلی توی دنیای برنامه نویسی داریم: Imperative (دستوری) یا Declarative (اعلانی یا توصیفی). در برنامه نویسی دستوری ما خودمون قدم به قدم به سیستم می گیم چطور باید به یک نتیجه ی خاص برسه اما در برنامه نویسی اعلانی ما به سیستم نتیجه ی مورد نظرمون رو اعلام می کنیم و دیگه کار نداریم سیستم چطور می خواد به این نتیجه برسه، فقط نتیجه برامون مهمه. به زبان ساده:

  • دستوری: چطوری انجامش بدم؟
  • اعلانی: چی کار کنم؟

مثلا فرض کنید یه آرایه از اعداد داریم و می خوایم همشون رو به توان ۲ برسونیم. روش دستوری اینطوری میشه:

const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = [];

for (let i = 0; i < numbers.length; i++) {
squaredNumbers.push(numbers[i] * numbers[i]);
}

console.log(squaredNumbers);
// [1, 4, 9, 16, 25] خروجیمون این شکلیه

یعنی روی تک تک اعضای آرایه گردش کردیم و تک تک اعداد رو در خودشون ضرب کردیم. روش اعلانیش اینطوری میشه:

const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);

console.log(squaredNumbers);
// [1, 4, 9, 16, 25] نتیجه همونه اما روش فرق داره

حالا این کد رو که یادتونه؟

<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML"
>
روی من کلیک کن!
</button>

اگر دقت کرده باشید روش HTMX هم اعلانی هست چون ما خط به خط مشخص نمی کنیم چی کار کنه، فقط بهش می گیم فلان کار رو انجام بده.

طبیعتا برای مرورگر ها چنین دستوراتی با پیشوند hx- معنی نداره و نمی‌فهمن معنی این دستورات چیه. HTMX یک کتابخانه ی جاوا اسکریپتی خیلی کوچک است که به مرورگر شما این قدرت رو میده. حجم این کتابخانه در حد ۱۰ کیلوبایت به صورت مینیفای و gzip شده است. برای مقایسه باید بگم که react-dom توی نسخه ی ۱۸ به تنهایی ۵۰ کیلوبایت هست (اون هم به صورت مینیفای و gzip شده). البته یه کم بالا پایین شدن این حجم ها رو قبول داشته باشید چون از نسخه به نسخه تغییر می‌کنن و بستگی داره minify و gzip شده باشن یا خیر.

HTMX به سرور شما متصل نیست و مثل react فقط در سمت کاربر (client side) کار می کنه در سمت کاربر مشغول مدیریت درخواست های AJAX برای به روز رسانی بخش های مختلف صفحه میشه. هدف اصلی React به عنوان مثلا یک کتابخانه ی کامل طراحی اینترفیس هست اما هدف اصلی HTMX اینه که شما همون صفحات عادی خودتون رو داشته باشید و تعامل پذیری بیشتری رو با HTMX ایجاد کنید تا حتی کاربرانی که جاوا اسکریپت ندارن هم بتونن از صفحات شما استفاده کنن (اگه کل برنامه ی شما با React باشه ولی مرورگر کاربر جاوا اسکریپت قبول نکنه، هیچی بالا نمیاد). با این حساب شما حتی می تونید HTMX رو با فریم ورک های کامل ترکیب صنعتی سنتی کنید و صاف تحویل کاربر بدید تا یاتاقان بزنن!

در عین حال HTMX به راحتی با رویداد های سرور (SSE یا Server Side Events) یا حتی Web Socket ها ترکیب میشه. به طور مثال ممکنه سرور شما بر اساس اتفاقی که توی پایگاه داده افتاده یک آپدیت انجام بده یا مثلا یک نوتیفیکیشن ارسال کنه. HTMX به راحتی به این رویداد ها گوش می ده و واکنش مناسب رو نشون میده. اگر نمی دونید SSE چیه می تونید از صفحه ی توسعه دهندگان موزیلا مطالعه کنید.

هشدار

هشـــدار!

توجه داشته باشید که از نسخه ی 2.0 به بعد قراره قابلیت کار با SSE و Websocket ها به عنوان افزونه (extension) باشه و از کتابخونه ی اصلی جدا میشه اما فعلا جزئی از هسته ی کتابخونه هستن.

HTMX یک بخش اصلی داره که هسته ی برنامه ی شما است و در اصل فقط HTML ساده است که HTMX یکم رنگ آمیزیش کرده و بهش جون داده و یک بخش دیگه داره که قابلیت های بیشتر هستن. چرا؟ با این کار اگه جاوا اسکریپت مرورگر از کار بیوفته برنامه تون از بیخ نابود نمیشه. چرا؟ اون کد <a> رو یادتونه؟ اگر HTMX نباشه نهایتا مرورگر فکر می کنه hx-post فقط یک اتریبیوت بی معنی هست که شما نوشتین و بهش کاری نداره. پس لینک همون لینک میمونه و هنوز کار می کنه اما قابلیت های اضافه اش رو از دست می ده (مثلا دیگه از درخواست AJAX استفاده نمی کنه و مثل لینک عادی عمل می کنه).

می تونید مثال های بیشتری رو از توضیح رسمی HTMX درباره‌ی بهبود افزایشی ببینید.

اگه با کتابخونه هایی مثل tailwind.css آشنا باشید می دونید که یکی از بزرگترین انتقاداتش اینه که HTML رو زشت می کنه چون کلی کلاس مختلف رو باید به عناصر مختلف اضافه کنیم. حالا سوال پیش میاد که HTMX هم همین کار رو نمی کنه؟ نه! اولا دستورات HTMX محدود هستن و مثل کلاس های tailwind پرتعداد نیستن و دوما HTMX قابلیت ارث بری رو برای اتریبیوت های خودش پیاده کرده! یعنی چی؟ یعنی یک اتریبیوت روی یک المان HTML روی المان های فرزند هم در دسترس هست تا تکرار کد (code duplication) نداشته باشیم. به طور مثال در HTMX یک اتریبیوت به نام hx-confirm داریم که قبل از انجام عملیات های حساس از کاربر می خواد صریحا اون عملیات رو تایید کنه.

<button hx-delete="/account" hx-confirm="آیا مطمئن هستید؟">
حسابم رو حذف کن
</button>
<button hx-put="/account" hx-confirm="آیا مطمئن هستید؟">
تغییرات رو ذخیره کن
</button>

همونطور که می بینید اتریبیوت hx-confirm دو بار تکرار شده. برای تمیز تر کردن کد میتونیم اینطوری بنویسیم:

<div hx-confirm="آیا مطمئن هستید؟">
<button hx-delete="/account">
حسابم رو حذف کن
</button>
<button hx-put="/account">
تغییرات رو ذخیره کن
</button>
</div>

با این کار اتریبیوت hx-confirm روی هر دو دکمه حضور داره بدون اینکه نیاز به ذکر شدن جداگانه داشته باشه. باحاله نه؟

HTMX سمت کاربر (client side) اجرا میشه بنابراین می تونید اون رو در هر فضایی که کلاینت ساید محسوب میشه پیاده کنید. به طور مثال اگر برنامه ی ساده ای دارید و فقط داخل مرورگر ازش استفاده می کنید، کافیه اسکریپت HTMX رو به صورت یک <script> ساده در کد HTML خودتون قرار بدین:

<script src="https://unpkg.com/htmx.org@1.9.9" integrity="sha384-QFjmbokDn2DjBjq+fM+8LUIVrAgqcNW2s0PjAxHETgRn9l4fvX31ZxDxvwQnyMOX" crossorigin="anonymous"></script>

همیشه می تونین از صفحه ی unpkg یا هر CDN دیگه ای اسکریپت ها رو دریافت کنید. اگر نمی خواین از CDN استفاده کنید، می تونید یک نسخه ی مینیفای شده رو از همین CDN ها دانلود کنید و به صورت محلی بارگذاری کنید:

<script src="/path/to/htmx.min.js"></script>

می تونید از این لینک unpkg همیشه آخرین نسخه رو مستقیما دریافت کنید.

و طبیعتا میشه از npm هم با دستور زیر دانلودش کرد:

npm install htmx.org

یه نگاه به کد HTMX زیر بندازین:

<!-- یک دکمه ی ساده که درخواست ایجکس ما رو به سرور ارسال می کنه -->
<button hx-get="/data" hx-target="#result-container">بارگذاری داده</button>
<div id="result-container"></div>

با کلیک روی این دکمه یک سری داده از سرور گرفته میشه و درون result-container قرار داده میشه. اگر بخوایم همین کد رو با React بنویسیم چی میشه؟

import { useState, useEffect } from 'react';

const ExampleComponent = () => {
const [data, setData] = useState('');

const fetchData = async () => {
try {
const response = await fetch('/data');
const responseData = await response.text();
setData(responseData);
} catch (error) {
console.error('Error fetching data:', error);
}
};

useEffect(() => {
// بعد از بارگذاری کامپوننت تابع خودمون رو اجرا می کنیم
fetchData();
}, []);

return (
<div>
{/* محل قرار گیری داده های دریافت شده */}
<div>{data}</div>
</div>
);
};

export default ExampleComponent;

اوه اوه چقدر طولانیه! واه واه خاک بر سر متا! نه؟ نه!

فلسفه ی HTMX که معمولا بهش JS-in-HTML میگن مفهوم جدیدی نیست و HTMX اصلا صاحب این فلسفه حساب نمیشه. خیلی از کتابخونه های قدیمی تر مثل Alpine قبلا این کار رو انجام دادن. طبیعتا این فلسفه معایبی هم داره:

  • HTMX در ظاهر فقط متن و اتریبیوته بنابراین syntax highlighting یا linting یا تحلیل استاتیک نداره.
  • هیچ مکانیسمی برای type-safe کردنش نداریم. یعنی مثل تایپ اسکریت نیست و یک خطا می‌تونه کل برنامه رو خراب کنه.
  • دیباگ کردن HTMX دردسر های خاص خودش رو داره.

ما قبلا چنین روش هایی رو تست کردیم. در اصل jQuery و امثالش خودشون یه جورایی همین HTMX بودن، فقط رنگ و لعاب HTMX خوشگل تره و گرنه اگه یادتون باشه ما با همین jQuery خودمون هم درخواست Ajax می دادیم دیگه! منتها HTMX راحت ترش کرده. ما اون زمان دلایل واضحی برای مهاجرت از jQuery داشتیم بنابراین HTMX هم از این قاعده مستثنی نیست.

 

HTMX فقط برای پروژه های کوچیک عالیه و شخصا هیچ دلیلی نمی بینم که یک پروژه ی ساده با HMTX نوشته نشه، بلکه پیشنهاد شخصی من هست اما برای پروژه های بزرگتر مطمئن باشید به جایی میرسه که موهاتون رو از سرتون می کَنین!

خارج از تصور کسی نیست که جامعه ی آماری HTMX خیلی کوچیک تر از react و vue و svelte و امثالشون هست. HTMX هنوز خیلی تازه وارده (حمل بر بد بودنش نشه!) بنابراین جامعه ی آماریش خیلی کوچیکه و توی گیت هاب حدود ۲۵ هزار ستاره داره در حالی که فریم ورکی مثل react تقریبا ۲۱۶ هزار ستاره داره. تعداد دانلود های NPM این پکیج هم حدود ۴۴ هزار تا است در مقابل react که حدود ۲۱ میلیون هست! شرکت های بزرگ و غول های دنیای دیجیتال از react استفاده می کنن و پشتوانه اش و شرکت مادرش هم متا (همون فیسبوک) هست که نیازی به معرفی نداره.

آمار صفحه ی گیت هاب پروژه ی HTMX
آمار صفحه ی گیت هاب پروژه ی HTMX

حالا اصلا مهمه؟ بله! با هر پروژه و تکنولوژی که کار می کنید بالاخره یه جایی به مشکل می خورید و داشتن جامعه ی آماری بالا به این معنیه که احتمالا قبل از شما یک بدبختی به همون مشکل برخورده و رفته ته و توش رو درآورده و جوابش رو حاضر و آماده برای شما گذاشته! وقتی جامعه ی آماری بالا باشه افراد بیشتری برای کمک به شما هستن اما هر چی جامعه کوچیک تر باشه شما در مواجهه با مشکلات تنها تر هستین. البته پروژه هایی که با HTMX نوشته میشن کوچیک هستن و احتمال درگیری های جدی ندارن. از طرفی هم با نگاهی که من روی بخش مشکلات صفحه ی گیت هابشون انداختم، معلوم شد که تیمشون در حد توان و به موقع پاسخگو هستن که عالیه. با این حساب برای پروژه های پیچیده (حداقل فعلا) روی HTMX سرمایه گذاری نکنید ولی خوراک پروژه های کوچیک تره!

برای مشاهده لیست پروژه هایی که با HTMX ساخته شدن به لینک رسمی HTMX برین: htmx.org/webring

شاید از این مقالات نیز خوشتان بیاید:

sample

ساخت هوک (hook) در React

در چند سال اخیر اکثر برنامه نویس های react از سمت کامپوننت های کلاسی دور شدن و به سمت کامپوننت های تابعی رفتن. به همین خاطر استفاده از hook هایی مثل useState و useEffect خیلی رایج شده اما آیا میشه خودمونم hook های شخصی بسازیم و توی برنامه های react ازشون استفاده کنیم؟ قطعا میشه و یکی از بهترین راه های ننوشتن کد اضافی در react همین کار هست. در...

sample

نصب و پیکربندی مقدماتی Nginx

Nginx یکی از مشهور ترین وب سرور ها و همچنین reverse proxy server ها در دنیای وب حساب میشه و اگر بخواین خودتون اون رو روی سرورتون تنظیم کنین باید بدونین که یکم دنگ و فنگ داره و دانش فنی می خواد. این مقاله به شما یاد میده چطور Nginx رو برای سرور سایت خودتون نصب و پیکربندی کنین تا یکم تجربه ی DevOps هم داشته باشیم دیگه!