Logo
KangTLee's blog

แนะนำการใช้ HTMX กับ Go: สร้างแอปพลิเคชัน Todo List แบบ Interactive อย่างรวดเร็ว

Kang T Lee
อัพเดทล่าสุดวันที่ 01 ตุลาคม 2567
แนะนำการใช้ 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 มีข้อดีหลายประการ:

  1. Server-Side Rendering ที่มีประสิทธิภาพ: Go เหมาะกับการทำ Server-Side Rendering อยู่แล้ว และ HTMX ช่วยให้เราอัพเดทเฉพาะส่วนของหน้าเว็บได้ ทำให้แอปของเรารวดเร็วและตอบสนองได้ดี

  2. ลดความซับซ้อนของ Frontend: เราสามารถใช้ Go templates และ server-side logic เป็นหลัก โดยไม่ต้องพึ่ง JavaScript frameworks ที่ซับซ้อน ช่วยประหยัดเวลาในการเรียนรู้และพัฒนา (เว้นแต่หากตัวแอพมีความ interative สูง การใช้ Javascript Framework อย่าง React อาจจะเหมาะกว่า)

  3. ประสิทธิภาพสูง: Go ประมวลผลได้เร็วบน server-side ในขณะที่ HTMX ช่วยลดปริมาณข้อมูลที่ส่งระหว่าง client และ server ทำให้แอปของเราเร็วและใช้ทรัพยากรน้อย

  4. การพัฒนาที่รวดเร็ว: เราสามารถสร้าง 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

ตัวอย่างแอพ Todo List ที่เขียนด้วย HTMX และ Go

หากต้องการดู Code ตัวอย่าง สามาถเข้าไปดูได้ที่ todo-htmx-go

อธิบายการทำงานของ HTMX

ในตัวอย่างนี้ เราได้ใช้ attribute ของ HTMX ที่จะทำงานดังนี้:

  1. hx-post="/add-todo": ส่ง POST request ไปยัง "/add-todo" เมื่อ form ถูก submit

  2. hx-target="#todo-list": กำหนดเป้าหมายที่จะอัพเดทเนื้อหา

  3. hx-swap="beforeend": กำหนดวิธีการแทรกเนื้อหาใหม่ (ในที่นี้คือเพิ่ม Todo Item ต่อท้าย)

  4. hx-indicator="#loading": แสดง loading state ระหว่างที่กำลัง fetch ข้อมูลจาก Server

  5. hx-on::after-request="...": รีเซ็ต form หลังจากส่งข้อมูลสำเร็จ โดยเราจะใช้ javascript ในการสั่งการล้างข้อมูลใน form

ข้อเสียและข้อควรระวังในการใช้ HTMX

แม้ว่า HTMX จะมีข้อดีหลายประการ แต่ก็มีข้อเสียและข้อควรระวังที่เราควรพิจารณาก่อนนำไปใช้ในโปรเจค:

  1. ไม่มี Type Safety: HTMX ทำงานผ่าน HTML attributes ซึ่งไม่มีการตรวจสอบประเภทข้อมูล (type checking) เหมือนกับภาษาที่มี static typing อย่าง TypeScript หรือ Go นี่อาจนำไปสู่ข้อผิดพลาดที่ตรวจจับได้ยากในระหว่างการพัฒนา

  2. โค้ดอาจรกเมื่อระบบซับซ้อนขึ้น: เมื่อแอปพลิเคชันมีขนาดใหญ่ขึ้นและซับซ้อนมากขึ้น การจัดการ HTMX attributes ใน HTML อาจทำให้โค้ดดูรกและยากต่อการบำรุงรักษา เราอาจต้องพิจารณาการแยกส่วนและจัดโครงสร้างโค้ดอย่างระมัดระวัง

  3. มี Library ให้เลือกใช้น้อยกว่า: เมื่อเทียบกับ JavaScript frameworks ยอดนิยมอย่าง React หรือ Vue การใช้ HTMX ที่ยังใหม่และมีคนใช้น้อยอาจหมายความว่าคุณอาจต้องพัฒนาทุกอย่างด้วยตนเองทั้งหมด ซึ่งจะต่างกับการใช้ Javascript ที่มีหลายครั้งเราไม่จำเป็นต้องเขียนฟังก์ชั่นใหม่ขึ้นมาเอง ดังนั้นความเร็วในการ Develope ก็อาจจะช้ากว่ามาก

  4. ไม่มี Hot Reload: ไม่เหมือนกับ JavaScript frameworks สมัยใหม่ที่มีฟีเจอร์ Hot Reload ซึ่งช่วยให้เห็นการเปลี่ยนแปลงทันทีโดยไม่ต้อง refresh ในขณะที่หากเราใช้ HTMX ร่วมกับ Go เราจะต้องทำการ compile code ใหม่ทุกครั้ง

  5. การ Debug อาจยากขึ้น: จากข้อเสียที่กล่าวมา ทำให้ความเร็วในการพัฒนา code หรืออาจที่เราจะต้อง Debug เมื่อเกิดปัญหา มีความล่าช้าและยุ่งยากกว่าการใช้ Javascript (Typescript)

แม้จะมีข้อเสียเหล่านี้ แต่ HTMX ก็ยังเป็นเครื่องมือที่มีประโยชน์มากสำหรับโปรเจคที่เหมาะสม การพิจารณาข้อดีและข้อเสียอย่างรอบคอบจะช่วยให้เราตัดสินใจได้ว่า HTMX เหมาะกับโปรเจคของเราหรือไม่

สรุป

การใช้ HTMX ร่วมกับ Go ช่วยให้เราสามารถสร้างแอปพลิเคชันแบบ interactive ได้อย่างรวดเร็วและมีประสิทธิภาพ โดยไม่ต้องเขียน JavaScript มากนัก เหมาะสำหรับผู้ประกอบการหรือนักพัฒนาที่ต้องการสร้างโปรโตไทป์หรือ MVP อย่างรวดเร็ว

ลองนำความรู้นี้ไปประยุกต์ใช้กับโปรเจคของคุณดูนะครับ และอย่าลืมแชร์ประสบการณ์การใช้ HTMX กับ Go ของคุณในคอมเมนต์ด้านล่างนี้ด้วยนะครับ! หากมีคำถามหรือข้อสงสัยใดๆ สามารถถามได้เลยครับ

แล้วพบกันใหม่ในบทความหน้า ขอให้สนุกกับการโค้ดครับ! 😊🚀

Kang T Lee

Kang T Lee

ผม Kang T Lee ผมเขียนบทความเกี่ยวกับ Web development, IC Design, Business and Entrepreneur และเนื้อหาที่น่าสนใจจากหนังสือที่ผมอ่าน

Tags:

บทความที่เกี่ยวข้อง