แนะนำการใช้ HTMX กับ Go: สร้างแอปพลิเคชัน Todo List แบบ Interactive อย่างรวดเร็ว
สวัสดีชาว Developer ทุกท่าน เคยรู้สึกไหมครับว่าการสร้างเว็บแอปพลิเคชันแบบ interactive นั้นใช้เวลานานและซับซ้อนเกินไป? หรือบางครั้งรู้สึกว่าต้องเขียน JavaScript มากเกินความจำเป็น? วันนี้เรามีวิธีแก้ปัญหานี้ด้วยการใช้ HTMX ร่วมกับ Go เพื่อสร้างแอปพลิเคชัน Todo List แบบ Interactive อย่างรวดเร็วและมีประสิทธิภาพ
HTMX คืออะไร และทำไมถึงใช้ร่วมกับ Go?
HTMX เป็น JavaScript Library ขนาดเล็กที่ช่วยให้เราสร้าง UI แบบ interactive ได้โดยใช้ HTML attributes พิเศษ โดยไม่ต้องเขียน JavaScript มากนัก นอกจากนี้เรายังสามารถใช้ร่วมกับ Go เพื่อพัฒนาเป็น Fullstack Application ทำให้เราสามารถแสดงผลเว็บไซท์แบบ Server-side Rendering ได้
การใช้ HTMX ร่วมกับ Go มีข้อดีหลายประการ:
Server-Side Rendering ที่มีประสิทธิภาพ: Go เหมาะกับการทำ Server-Side Rendering อยู่แล้ว และ HTMX ช่วยให้เราอัพเดทเฉพาะส่วนของหน้าเว็บได้ ทำให้แอปของเรารวดเร็วและตอบสนองได้ดี
ลดความซับซ้อนของ Frontend: เราสามารถใช้ Go templates และ server-side logic เป็นหลัก โดยไม่ต้องพึ่ง JavaScript frameworks ที่ซับซ้อน ช่วยประหยัดเวลาในการเรียนรู้และพัฒนา (เว้นแต่หากตัวแอพมีความ interative สูง การใช้ Javascript Framework อย่าง React อาจจะเหมาะกว่า)
ประสิทธิภาพสูง: Go ประมวลผลได้เร็วบน server-side ในขณะที่ HTMX ช่วยลดปริมาณข้อมูลที่ส่งระหว่าง client และ server ทำให้แอปของเราเร็วและใช้ทรัพยากรน้อย
การพัฒนาที่รวดเร็ว: เราสามารถสร้าง backend ด้วย Go และ frontend ที่ตอบสนองด้วย HTMX ได้อย่างรวดเร็ว เหมาะสำหรับผู้ที่ต้องการสร้างโปรโตไทป์หรือ MVP อย่างเร่งด่วน
ด้วยข้อดีเหล่านี้ เรามาเริ่มสร้างแอป Todo List กันเลยครับ!
การตั้งค่าโปรเจค
เริ่มต้นด้วยการสร้างโปรเจคใหม่:
go mod init github.com/punkzberryz/todo-htmx-go
โครงสร้างโปรเจคของเราจะเป็นดังนี้:
/todo-htmx-go
-- /cmd
------ /main.go
-- /template
------ /index.html
เราแยกโค้ด Go และ HTML template ออกจากกันเพื่อให้ง่ายต่อการจัดการโปรเจ็ค
การสร้าง HTTP Route สำหรับแอป Todo
เริ่มจากการสร้าง HTTP route สำหรับแอป Todo ของเรา:
// ./cmd/main.go
package main
import (
"log"
"net/http"
"html/template"
)
type Todo struct {
Title string
Description string
Completed bool
}
func main() {
http.HandleFunc("/", getTodos)
log.Println("Starting server on <http://localhost:8080>")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("Error starting server: ", err)
}
}
func getTodos(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("./template/index.html"))
todos := []Todo{
{Title: "Task 1", Description: "Description 1", Completed: false},
{Title: "Task 2", Description: "Description 2", Completed: true},
{Title: "Task 3", Description: "Description 3", Completed: false},
}
tmpl.Execute(w, todos)
}
เราเริ่มจากการสร้าง struct Todo
เพื่อเก็บข้อมูลของแต่ละรายการ และฟังก์ชัน getTodos
เพื่อแสดงรายการ Todo ทั้งหมด โดยจะแสดงผลที่ได้ด้วยโดยใช้หน้า html จากไฟล์ ./template/index.html ที่ route http://localhost:8080/
การสร้าง HTML Template
สร้างไฟล์ HTML สำหรับหน้าหลักของเรา:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TODO</title>
<script src="<https://unpkg.com/[email protected]>"></script>
</head>
<body>
<h1>TODO</h1>
<ul id="todo-list">
{{range .}} {{block "todo-list-element" .}}
<li>
<div>{{.Title}}</div>
<div>{{.Description}}</div>
<div>is completed ? {{.Completed}}</div>
</li>
{{end}} {{end}}
</ul>
<div>
<form
hx-post="/add-todo"
hx-target="#todo-list"
hx-swap="beforeend"
hx-indicator="#loading"
hx-on::after-request="if(event.detail.successful) this.reset()"
>
<div>
<label for="title">Title</label>
<input type="text" id="title" name="title" required />
</div>
<div>
<label for="description">Description</label>
<input type="text" id="description" name="description" required />
</div>
<div>
<label for="completed">Completed</label>
<input type="checkbox" id="completed" name="completed" />
</div>
<button type="submit">
<span class="htmx-indicator" id="loading">loading...</span>
<span>Add</span>
</button>
</form>
</div>
</body>
</html>
ในTemplate นี้ เราจะใช้ HTMX attributes เพื่อทำให้ form สามารถส่งข้อมูลและอัพเดทหน้าเว็บแบบ dynamic ได้ สังเกตว่าเราไม่ต้องเขียน JavaScript เพิ่มเติมเลย แต่สิ่งที่จะช่วยให้เว็บไซต์สามารถรัน HTMX ได้คือการโหลด script จาก head tag
<head>
...
<script src="<https://unpkg.com/[email protected]>"></script>
</head>
และเราจะเห็นว่าตัว <form> ได้มีการใส่ htmx attribute ที่จะช่วยให้ form ส่งค่า POST request เมื่อเรากดปุ่ม Add ด้วย hx-post=”/add-todo”
ซึ่งจะเป็นการส่ง formData ไปยัง route /add-todo นั่นเอง
การเพิ่ม POST Route สำหรับการเพิ่ม Todo
ต่อไปเราจะเพิ่ม POST route สำหรับการเพิ่ม todo item:
// main.go
func main() {
// ...
http.HandleFunc("/add-todo", addTodo)
// ...
}
func addTodo(w http.ResponseWriter, r *http.Request) {
title := r.PostFormValue("title")
description := r.PostFormValue("description")
completed := r.PostFormValue("completed") == "on"
templ := template.Must(template.ParseFiles("./template/index.html"))
templ.ExecuteTemplate(w, "todo-list-element", Todo{Title: title, Description: description, Completed: completed})
}
ฟังก์ชัน addTodo
นี้จะรับข้อมูลจาก form และสร้าง Todo item ใหม่ จากนั้นส่งกลับเฉพาะส่วนของ HTML ที่แสดง Todo item นั้น ซึ่งจะถูกเพิ่มเข้าไปในหน้าเว็บโดย HTMX
เพียงแค่นี้ เราก็จะได้แอพ Todo List ที่เขียนโดยใช้ Go และ HTMX
หากต้องการดู Code ตัวอย่าง สามาถเข้าไปดูได้ที่ todo-htmx-go
อธิบายการทำงานของ HTMX
ในตัวอย่างนี้ เราได้ใช้ attribute ของ HTMX ที่จะทำงานดังนี้:
hx-post="/add-todo"
: ส่ง POST request ไปยัง "/add-todo" เมื่อ form ถูก submithx-target="#todo-list"
: กำหนดเป้าหมายที่จะอัพเดทเนื้อหาhx-swap="beforeend"
: กำหนดวิธีการแทรกเนื้อหาใหม่ (ในที่นี้คือเพิ่ม Todo Item ต่อท้าย)hx-indicator="#loading"
: แสดง loading state ระหว่างที่กำลัง fetch ข้อมูลจาก Serverhx-on::after-request="..."
: รีเซ็ต form หลังจากส่งข้อมูลสำเร็จ โดยเราจะใช้ javascript ในการสั่งการล้างข้อมูลใน form
ข้อเสียและข้อควรระวังในการใช้ HTMX
แม้ว่า HTMX จะมีข้อดีหลายประการ แต่ก็มีข้อเสียและข้อควรระวังที่เราควรพิจารณาก่อนนำไปใช้ในโปรเจค:
ไม่มี Type Safety: HTMX ทำงานผ่าน HTML attributes ซึ่งไม่มีการตรวจสอบประเภทข้อมูล (type checking) เหมือนกับภาษาที่มี static typing อย่าง TypeScript หรือ Go นี่อาจนำไปสู่ข้อผิดพลาดที่ตรวจจับได้ยากในระหว่างการพัฒนา
โค้ดอาจรกเมื่อระบบซับซ้อนขึ้น: เมื่อแอปพลิเคชันมีขนาดใหญ่ขึ้นและซับซ้อนมากขึ้น การจัดการ HTMX attributes ใน HTML อาจทำให้โค้ดดูรกและยากต่อการบำรุงรักษา เราอาจต้องพิจารณาการแยกส่วนและจัดโครงสร้างโค้ดอย่างระมัดระวัง
มี Library ให้เลือกใช้น้อยกว่า: เมื่อเทียบกับ JavaScript frameworks ยอดนิยมอย่าง React หรือ Vue การใช้ HTMX ที่ยังใหม่และมีคนใช้น้อยอาจหมายความว่าคุณอาจต้องพัฒนาทุกอย่างด้วยตนเองทั้งหมด ซึ่งจะต่างกับการใช้ Javascript ที่มีหลายครั้งเราไม่จำเป็นต้องเขียนฟังก์ชั่นใหม่ขึ้นมาเอง ดังนั้นความเร็วในการ Develope ก็อาจจะช้ากว่ามาก
ไม่มี Hot Reload: ไม่เหมือนกับ JavaScript frameworks สมัยใหม่ที่มีฟีเจอร์ Hot Reload ซึ่งช่วยให้เห็นการเปลี่ยนแปลงทันทีโดยไม่ต้อง refresh ในขณะที่หากเราใช้ HTMX ร่วมกับ Go เราจะต้องทำการ compile code ใหม่ทุกครั้ง
การ Debug อาจยากขึ้น: จากข้อเสียที่กล่าวมา ทำให้ความเร็วในการพัฒนา code หรืออาจที่เราจะต้อง Debug เมื่อเกิดปัญหา มีความล่าช้าและยุ่งยากกว่าการใช้ Javascript (Typescript)
แม้จะมีข้อเสียเหล่านี้ แต่ HTMX ก็ยังเป็นเครื่องมือที่มีประโยชน์มากสำหรับโปรเจคที่เหมาะสม การพิจารณาข้อดีและข้อเสียอย่างรอบคอบจะช่วยให้เราตัดสินใจได้ว่า HTMX เหมาะกับโปรเจคของเราหรือไม่
สรุป
การใช้ HTMX ร่วมกับ Go ช่วยให้เราสามารถสร้างแอปพลิเคชันแบบ interactive ได้อย่างรวดเร็วและมีประสิทธิภาพ โดยไม่ต้องเขียน JavaScript มากนัก เหมาะสำหรับผู้ประกอบการหรือนักพัฒนาที่ต้องการสร้างโปรโตไทป์หรือ MVP อย่างรวดเร็ว
ลองนำความรู้นี้ไปประยุกต์ใช้กับโปรเจคของคุณดูนะครับ และอย่าลืมแชร์ประสบการณ์การใช้ HTMX กับ Go ของคุณในคอมเมนต์ด้านล่างนี้ด้วยนะครับ! หากมีคำถามหรือข้อสงสัยใดๆ สามารถถามได้เลยครับ
แล้วพบกันใหม่ในบทความหน้า ขอให้สนุกกับการโค้ดครับ! 😊🚀
Kang T Lee
ผม Kang T Lee ผมเขียนบทความเกี่ยวกับ Web development, IC Design, Business and Entrepreneur และเนื้อหาที่น่าสนใจจากหนังสือที่ผมอ่าน