- ผมชอบแนวคิดพื้นฐานที่เรียบง่ายของ 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 ความคิดเห็น
ความสนใจย่อมดีกว่าความไม่สนใจอยู่แล้ว~ ผมชอบ HTMX นะ รวมถึงปรัชญาของมันด้วย
มันมีแนวทางที่คล้ายกับ SQLite มากเลยครับ 555
อะไรคือสิ่งที่ SQLite กับ HTMX มีเหมือนกัน?
คล้ายกับ Sqlite ไหม?
คอมเมนต์นี้ลุ่มลึกมาก ถึงขั้นเป็นปรัชญาเลยทีเดียว..
ถ้าคุณเคยมีประสบการณ์พัฒนาเว็บด้วยการเรนเดอร์ฝั่งเซิร์ฟเวอร์และ jQuery ก่อนยุคที่ SPA จะถือกำเนิดขึ้น ก็น่าจะเข้าใจได้ทันทีว่านี่คือเทคโนโลยีแนวนั้น ผมคิดว่าคนที่เริ่มต้นพัฒนาเว็บจาก SPA แล้วพยายามมองหาสิ่งใหม่ ๆ อาจกำลังเข้าใจผิดอยู่
บทความนี้ดูเหมือนจะไม่ได้เขียนขึ้นในเกาหลีเสียด้วยซ้ำ
ก็จริงนะครับ/ค่ะ มันดูเหมือนเป็นเครื่องมือที่สร้างมาสำหรับหน้าเว็บง่าย ๆ แต่ผม/ฉันไม่เข้าใจว่าทำไมถึงมีการถกเถียงกัน โดยยกตัวอย่างหรือ use case แปลก ๆ ขึ้นมา แล้วบอกว่ามันไม่เหมาะกับสิ่งนั้น
อย่างที่เห็นได้จากหน้าแรกของ htmx, htmx มีจุดยืนค่อนข้างชัดว่า (ถ้ามีแค่พวกเขาเอง) ก็ไม่จำเป็นต้องใช้เทคโนโลยีฟรอนต์เอนด์สมัยใหม่ รวมถึง React
นั่นเกี่ยวข้องกับเหตุผลที่ htmx ได้รับความสนใจครับ บทความนี้ก็เป็นงานแปลจากบทความเขียนโดยผู้เขียนต่างประเทศเหมือนกัน และในต่างประเทศหลายคนก็เริ่มเหนื่อยล้ากับการจัดการ state สารพัดแบบของ React กันแล้ว ดังนั้น htmx ที่ให้ความสามารถคล้ายกับ React แต่ไม่จำเป็นต้องจัดการ state แบบ React จึงถูกมองว่าเป็นทางเลือกทดแทน React เลยมีการนำ htmx ไปเปรียบเทียบกับ React อยู่เรื่อย ๆ ครับ
อืม ถ้าเป็นเหตุผลแบบนั้น ก็ควรยกสิ่งที่อ้างว่าสามารถมาแทน React ได้มาเปรียบเทียบไม่ใช่หรือ?
แค่ดูคุณสมบัติที่ลิสต์ไว้ในหน้านี้ก็เห็นแล้วว่า HTMX ไม่ใช่ของที่จะเอาไปใช้กับหน้าที่ซับซ้อนได้ และไม่ใช่อะไรที่สามารถมาแทน React ได้เลย
ความคิดเห็นบน Hacker News
มีความเห็นแตกต่างกันเรื่องการสืบทอดแอตทริบิวต์ สามารถปิดได้ด้วยตัวเลือก
htmx.config.disableInheritanceเหตุผลที่ไม่ได้กระโดดเข้าสู่ฝั่งฟรอนต์เอนด์คือมีตัวเลือกมาก คำวิจารณ์มาก และเทรนด์เทคโนโลยีเปลี่ยนบ่อย
กำลังใช้ HTMX สร้าง storefront ที่มีประสิทธิภาพดี และพอใจกับผลลัพธ์
ไอเดีย "HTMX in React" ก็เหมือนกับการคิด React Server Components ขึ้นมาใหม่
ไม่เห็นด้วยกับความเห็นที่ว่าโหมดคิวเริ่มต้นนั้นไม่มีเหตุผล
หลังจากลองใช้ HTMX ครั้งแรก พบว่านำไปใช้กับงานง่าย ๆ ได้สะดวกและสนุก
พออ่านคำบ่นเรื่องสถานะแล้ว ก็คิดว่าผู้เขียนอาจไม่เคยทำเว็บไซต์มาก่อนยุค React
สงสัยว่า HTMX มีฟีเจอร์แบบเดียวกับ Turbo Mount หรือไม่
อยากรู้เพิ่มเติมเกี่ยวกับปัญหาที่ morphdom เขียนทับบางองค์ประกอบโดยไม่คาดคิด