7 คะแนน โดย GN⁺ 2024-10-10 | 12 ความคิดเห็น | แชร์ทาง WhatsApp
  • ผมชอบแนวคิดพื้นฐานที่เรียบง่ายของ Htmx มากจริง ๆ แต่หลังจากลองใช้ทั้งทีมแล้วก็พบว่าในทางปฏิบัติมันไม่ได้เรียบง่าย และค่อนข้างซับซ้อน

การสืบทอดแอตทริบิวต์ของ Htmx เป็นความผิดพลาดอย่างชัดเจน

  • การสืบทอดแอตทริบิวต์ในโค้ดเป็นแบบแฝงและชวนให้ประหลาดใจ
  • เหมือนใน CSS การสืบทอดเป็นแฮ็กที่ทำง่ายแต่ต้องแลกมาด้วยต้นทุน
  • ขัดกับข้ออ้างเรื่อง locality of behavior ของผู้เขียน
  • ค่าเริ่มต้นของการสืบทอดแตกต่างกันไปในหลายแอตทริบิวต์ (เช่น hx-delete ไม่สืบทอด แต่ hx-confirm และ hx-ext สืบทอด)
  • ต้องจำข้อยกเว้น และสุดท้ายก็ต้องเขียนทุกอย่างแบบ explicit ทำให้การสืบทอดแทบไม่มีความหมาย

เว็บแอปที่น่าสนใจส่วนใหญ่ไม่สามารถแทนที่ DOM element ทั้งก้อนได้

  • DOM element แทบจะมีสถานะฝั่งเบราว์เซอร์ในตัวเสมอ (เช่น สถานะเปิด/ปิดของ <details>, ค่าที่กรอกใน <input>, สถานะเปิด/ปิดของ dropdown)
  • เมื่อ Htmx ใช้วิธีง่าย ๆ แบบแทนที่ outerHTML ตรง ๆ สถานะเหล่านี้จะหายไปทั้งหมด
  • แม้แต่ส่วนขยาย Morphdom ก็ยังเขียนทับบาง element แบบไม่ตรงกับที่คาดไว้

การเก็บ state ไว้ใน DOM element เองเป็นความคิดที่ไม่ดี

  • Morphdom มีไว้เพื่อแก้ความเจ็บปวดจากหัวข้อก่อนหน้า แต่ก็ทำให้เห็นว่าวิธีทำงานของ Htmx ตั้งอยู่บนแนวคิดการแทนที่ element ทั้งก้อน
  • มันเก็บ request queue ไว้บน DOM element เอง
  • เมื่อเริ่ม request ก็จะมี queue อยู่บน element นั้น หรือบน element อื่นที่อ้างถึงมัน
  • ถ้าแทนที่ DOM element ทั้งก้อน queue จะถูกรีเซ็ต ซึ่งช่วยเลี่ยง failure mode แย่ ๆ บางอย่างได้
  • แต่ใน Morphdom element ยังอยู่ต่อ ดังนั้น queue ก็ยังอยู่ต่อ
  • สุดท้ายจึงไปอยู่ในพื้นที่คล้าย undefined behavior ที่ละเมิดการออกแบบของ Htmx เอง

โหมด queue เริ่มต้นนั้นเละเทะ

  • โดยค่าเริ่มต้น ถ้า Htmx trigger request อื่นจาก queue เดียวกัน (element เดียวกัน) มันจะยกเลิก request ที่กำลังทำงานอยู่
  • และนี่คือกลยุทธ์ค่าเริ่มต้น
  • ผู้เขียนมารู้ทีหลังว่าเป็นแบบนี้
  • มันไม่ intuitive อย่างมาก และหมายถึงงานบางอย่างอาจหายไป

event trigger ไม่ได้มีความเป็น local

  • event trigger มักช่วยให้ทำให้บางสิ่งเกิดขึ้นได้ แต่ผลกระทบของมันไม่ได้อยู่เฉพาะจุด และมีปัญหาคล้ายกับการสืบทอดแอตทริบิวต์
  • ถ้าทำ DSL ในภาษา server-side ก็พอช่วยได้บ้าง แต่ก็ยังให้ความรู้สึกคล้ายการเขียนโปรแกรม JavaScript แบบ callback ยุคเก่า
  • เมื่อ event เกิดขึ้น ก็ “subscribe” แล้วทำบางอย่าง

รักษาสถานะของคอมโพเนนต์ได้ไม่ดี

  • ปัญหาที่กว้างกว่าซึ่งคล้ายกับเรื่องสถานะของ DOM element คือคอมโพเนนต์ของคุณเองก็มี state ของมัน
    • ตัวอย่างเช่น ถ้าคุณต้องการหน้าเว็บที่มีสามส่วน โดยมีทั้ง state ที่เซิร์ฟเวอร์ต้องใช้ (เช่น หน้าของชุดผลลัพธ์) และ state ที่ React หรือ WebComponents ต้องใช้ ก็จะเกิดปัญหาเรื่องการซิงก์ state ระหว่าง parent กับ child component
  • Htmx ไม่มีวิธีที่ดีสำหรับเรื่องนี้
    • มีแนวคิดอย่างการใช้ query parameter, hidden form input, event trigger ฯลฯ แต่ทุกแบบมีข้อควรระวังใหญ่ ๆ ทั้งนั้น
  • React และ Halogen มีคำตอบสำหรับเรื่องนี้
    • ในทั้งสองกรณี child component มี state ของตัวเอง และ parent สามารถส่ง “props” ที่คล้าย “คำแนะนำ” ลงมาได้
    • และมันก็ยังมี internal state ของตัวเอง ซึ่งอาจเพิกเฉยต่อ props หรือให้ความสำคัญมากกว่าก็ได้
    • โดยทั่วไป props มาจากเซิร์ฟเวอร์หรืออนุมานจากเซิร์ฟเวอร์ ส่วน state มักเป็นสถานะฝั่งไคลเอนต์
  • คอมโพเนนต์สำเร็จรูปที่มีให้ใช้กับ React หรือคอมโพเนนต์ที่จำเป็นต้องใช้ มักต้องพึ่ง React
    • React กับ Htmx ทำงานร่วมกันได้ไม่ค่อยดี
    • ผู้เขียนเคยลองทำงานกับ WebComponents แบบที่ยังไม่ค่อยน่าพอใจ และมันก็มีข้อจำกัดประหลาดที่คาดไม่ถึง
    • ผู้เขียนยังเคยทำ bridge ตรงไปยัง React component ที่ใช้ในภาษา server-side แต่โดยทั่วไปแล้ว Htmx กับ React มักปะทะกันเรื่องการไหลของ state และการจัดการ DOM element
    • ผู้เขียนลองใช้ Alpine แล้ว พบว่ามันดี แต่ก็เป็นไลบรารีเขียนโปรแกรมฝั่งไคลเอนต์อีกตัวหนึ่ง จึงซ้ำซ้อนหากใน codebase มี React อยู่แล้ว

ถึงอย่างนั้นก็ยังมีข้อดี

  • การใช้ภาษา server-side ได้เป็นข้อดีที่ชัดเจนมากและแทบไม่มีข้อโต้แย้ง
  • ไม่มีใครในทีมอยากเขียน business logic ทั้งหมดนี้ใหม่เป็น TypeScript
  • ไม่จำเป็นต้อง serialize จาก type ใน DB ไปเป็น type ฝั่ง frontend
    • จึงไม่มีการรั่วไหลของข้อมูล และไม่ต้องใช้ GraphQL ด้วย
  • ใช้ความสามารถด้าน abstraction ที่ทรงพลังยิ่งกว่าของภาษา server-side ได้
  • ใช้ form builder ของภาษา server-side ได้ แทนที่จะต้องทำ validation เดียวกันทั้งฝั่ง frontend และ backend
  • แต่ข้อเสียข้างต้นก็เป็นความจริงเช่นกัน

Htmx-in-React?

  • ทิศทางในอนาคตที่น่าสนใจอย่างหนึ่งคืออาจ reimplement Htmx ใหม่ใน React
    • ให้เซิร์ฟเวอร์ส่ง JSON blob มา แล้ว React แปลงเป็น virtual DOM component
    • แบบนั้นปัญหาเรื่องสถานะของคอมโพเนนต์ก็น่าจะถูกแก้
    • จะไม่ต้องมี bridge พิเศษเพื่อใช้ React component
    • ใช้ไลบรารี web fetching ที่ผูกกับ React ได้ และหลีกเลี่ยงตัวเลือกการ queue แบบหนึ่งของ Htmx อย่างระมัดระวังได้
    • ปัญหา Morphdom และปัญหาของ input element ใน browser DOM ก็น่าจะแก้ได้ด้วย เพราะใน React เรื่องเหล่านี้แทบเป็นปัญหาที่แก้ไปแล้ว
  • วิธีนี้อาจตัด dependency ของ Htmx ออกไป แต่ยังรักษาข้อดีของแนวคิดไว้ได้ ถ้ามีงบพอจะเริ่มงานขนาดนั้น

ความเห็นของ GN⁺

  • แนวคิดพื้นฐานของ Htmx นั้นน่าสนใจ แต่เมื่อใช้งานจริงอาจต้องเจอกับปัญหาซับซ้อนหลายอย่าง
  • การสืบทอดแอตทริบิวต์ การแทนที่ DOM element และโหมด queue เป็นตัวอย่างของการออกแบบบางส่วนใน Htmx ที่ไม่ intuitive และอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด
  • การรวมเข้ากับ React หรือ WebComponents ก็ดูจะไม่ง่ายเช่นกัน
  • ถึงอย่างนั้น การใช้ภาษา server-side ได้ก็ยังเป็นข้อดีมาก
  • ในอนาคต การ reimplement Htmx บน React ก็อาจเป็นทิศทางที่น่าสนใจได้

12 ความคิดเห็น

 
felizgeek 2024-10-10

ความสนใจย่อมดีกว่าความไม่สนใจอยู่แล้ว~ ผมชอบ HTMX นะ รวมถึงปรัชญาของมันด้วย
มันมีแนวทางที่คล้ายกับ SQLite มากเลยครับ 555

 
savvykang 2024-10-13

อะไรคือสิ่งที่ SQLite กับ HTMX มีเหมือนกัน?

 
aer0700 2024-10-12

คล้ายกับ Sqlite ไหม?

 
halfenif 2024-10-11

คอมเมนต์นี้ลุ่มลึกมาก ถึงขั้นเป็นปรัชญาเลยทีเดียว..

 
[ความคิดเห็นนี้ถูกซ่อน]
 
savvykang 2024-10-10

ถ้าคุณเคยมีประสบการณ์พัฒนาเว็บด้วยการเรนเดอร์ฝั่งเซิร์ฟเวอร์และ jQuery ก่อนยุคที่ SPA จะถือกำเนิดขึ้น ก็น่าจะเข้าใจได้ทันทีว่านี่คือเทคโนโลยีแนวนั้น ผมคิดว่าคนที่เริ่มต้นพัฒนาเว็บจาก SPA แล้วพยายามมองหาสิ่งใหม่ ๆ อาจกำลังเข้าใจผิดอยู่

 
heycalmdown 2024-10-10

บทความนี้ดูเหมือนจะไม่ได้เขียนขึ้นในเกาหลีเสียด้วยซ้ำ

 
ndrgrd 2024-10-10

ก็จริงนะครับ/ค่ะ มันดูเหมือนเป็นเครื่องมือที่สร้างมาสำหรับหน้าเว็บง่าย ๆ แต่ผม/ฉันไม่เข้าใจว่าทำไมถึงมีการถกเถียงกัน โดยยกตัวอย่างหรือ use case แปลก ๆ ขึ้นมา แล้วบอกว่ามันไม่เหมาะกับสิ่งนั้น

 
roxie 2024-10-11

อย่างที่เห็นได้จากหน้าแรกของ htmx, htmx มีจุดยืนค่อนข้างชัดว่า (ถ้ามีแค่พวกเขาเอง) ก็ไม่จำเป็นต้องใช้เทคโนโลยีฟรอนต์เอนด์สมัยใหม่ รวมถึง React

 
rlrsbtm80879 2024-10-10

นั่นเกี่ยวข้องกับเหตุผลที่ htmx ได้รับความสนใจครับ บทความนี้ก็เป็นงานแปลจากบทความเขียนโดยผู้เขียนต่างประเทศเหมือนกัน และในต่างประเทศหลายคนก็เริ่มเหนื่อยล้ากับการจัดการ state สารพัดแบบของ React กันแล้ว ดังนั้น htmx ที่ให้ความสามารถคล้ายกับ React แต่ไม่จำเป็นต้องจัดการ state แบบ React จึงถูกมองว่าเป็นทางเลือกทดแทน React เลยมีการนำ htmx ไปเปรียบเทียบกับ React อยู่เรื่อย ๆ ครับ

 
ndrgrd 2024-10-10

อืม ถ้าเป็นเหตุผลแบบนั้น ก็ควรยกสิ่งที่อ้างว่าสามารถมาแทน React ได้มาเปรียบเทียบไม่ใช่หรือ?

แค่ดูคุณสมบัติที่ลิสต์ไว้ในหน้านี้ก็เห็นแล้วว่า HTMX ไม่ใช่ของที่จะเอาไปใช้กับหน้าที่ซับซ้อนได้ และไม่ใช่อะไรที่สามารถมาแทน React ได้เลย

 
GN⁺ 2024-10-10
ความคิดเห็นบน Hacker News
  • มีความเห็นแตกต่างกันเรื่องการสืบทอดแอตทริบิวต์ สามารถปิดได้ด้วยตัวเลือก htmx.config.disableInheritance

    • สถานะฝั่งไคลเอนต์กับการสลับเนื้อหาของ htmx ไม่ได้เข้ากันได้ดีเสมอไป โดยเฉพาะในกรณีที่เรียบง่าย
    • อีเวนต์มีพลังมาก แต่ก็ซับซ้อนและดีบักยาก ซึ่งเป็นลักษณะของการเขียนโปรแกรมแบบอิงอีเวนต์
    • ไม่เห็นด้วยกับโหมดคิวเริ่มต้น เพราะแทนที่จะยกเลิกคำขอเดิมแล้วแทนที่ กลับคงคำขอปัจจุบันไว้และรอคิวคำขอเพิ่มได้เพียงหนึ่งรายการ
    • โปรโมตแก้วมัคสำหรับคนที่ไม่ชอบ htmx
  • เหตุผลที่ไม่ได้กระโดดเข้าสู่ฝั่งฟรอนต์เอนด์คือมีตัวเลือกมาก คำวิจารณ์มาก และเทรนด์เทคโนโลยีเปลี่ยนบ่อย

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

    • ผู้ค้าปลีกเสื้อผ้ารายใหญ่ในบราซิลกำลังใช้ HTMX และกลยุทธ์การเรนเดอร์บางส่วน
  • ไอเดีย "HTMX in React" ก็เหมือนกับการคิด React Server Components ขึ้นมาใหม่

    • เมื่อเซิร์ฟเวอร์ส่ง JSON มา React จะเปลี่ยนมันเป็นคอมโพเนนต์ virtual DOM
    • สามารถแก้ปัญหาเรื่องสถานะของคอมโพเนนต์ และใช้คอมโพเนนต์ React ได้โดยไม่ต้องมีบริดจ์พิเศษ
    • สามารถใช้ไลบรารี web fetching ที่เชื่อมกับ React และหลีกเลี่ยงตัวเลือกคิวของ HTMX ได้
    • สามารถแก้ปัญหาของ morphdom และปัญหาขององค์ประกอบรับอินพุตใน DOM ของเบราว์เซอร์ได้
    • RSC ยังอยู่ในช่วงทดลอง และการติดตั้งใช้งานพื้นฐานตั้งสมมติฐานว่ารัน JS บนเซิร์ฟเวอร์
  • ไม่เห็นด้วยกับความเห็นที่ว่าโหมดคิวเริ่มต้นนั้นไม่มีเหตุผล

    • ถ้าผู้ใช้ส่งข้อมูลเข้าไป แล้วเปลี่ยนแปลงระหว่างนั้นก่อนจะส่งอีกครั้ง คำขอควรถูกยกเลิก
    • หากการตอบกลับแทนที่เนื้อหาด้วย ID อื่น การตอบกลับครั้งที่สองก็ไม่สามารถแทนที่แบบเดียวกันได้
  • หลังจากลองใช้ HTMX ครั้งแรก พบว่านำไปใช้กับงานง่าย ๆ ได้สะดวกและสนุก

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

    • ตัวอย่างนั้นเข้าใจไม่ได้ และดูเหมือนพยายามใช้ htmx แบบเดียวกับ React แล้วผิดหวังเพราะไม่เป็นไปตามที่คาด
  • สงสัยว่า HTMX มีฟีเจอร์แบบเดียวกับ Turbo Mount หรือไม่

    • คิดว่าเป็นหนึ่งในวิธีที่ดีที่สุดในการใช้ Hotwire/Turbo
  • อยากรู้เพิ่มเติมเกี่ยวกับปัญหาที่ morphdom เขียนทับบางองค์ประกอบโดยไม่คาดคิด

    • การคงสถานะขององค์ประกอบ input และ detail ไว้เป็นฟังก์ชันหลักของไลบรารีอย่าง morphdom