Hotwire: เทคโนโลยี HTML over the wire
(hotwired.dev)- Hotwire เป็นแนวทางสำหรับสร้างเว็บแอปสมัยใหม่โดย ส่ง HTML แทน JSON มุ่งให้โหลดครั้งแรกได้เร็วและตอบสนองดีโดยไม่ต้องใช้ JavaScript มากนัก
- เนื่องจากยังคงให้การเรนเดอร์อยู่ที่ เทมเพลตฝั่งเซิร์ฟเวอร์ จึงช่วยให้เวิร์กโฟลว์การพัฒนายังคงเรียบง่ายได้ ไม่ว่าจะใช้ภาษาใดก็ตาม
- เฟรมเวิร์กที่ 37signals สร้างขึ้นเพื่อ HEY ถูกนำมาประกอบร่วมกันเป็น อีโคซิสเต็ม Hotwire ที่ต่อเนื่องตั้งแต่เว็บไปจนถึงหลายแพลตฟอร์ม
- องค์ประกอบหลักอย่าง Turbo จัดการการเปลี่ยนหน้า การส่งฟอร์ม การแบ่งคอมโพเนนต์ และการอัปเดตบางส่วนผ่าน WebSocket โดยไม่ต้องเขียน JavaScript
- การโต้ตอบแบบปรับแต่งเองที่ Turbo ยังไม่พอจะถูกเสริมด้วย Stimulus และ Hotwire Native ช่วยให้สร้างแอปมือถือแบบเนทีฟบนฐานของเว็บแอปเดิมได้
แนวทางที่เรนเดอร์ HTML จากเซิร์ฟเวอร์แล้วส่งไป
- Hotwire เป็นแนวทางทางเลือกสำหรับสร้างเว็บแอปพลิเคชันสมัยใหม่ด้วยวิธี HTML-over-the-wire
- ส่ง HTML ผ่านเครือข่าย แทน JSON ทำให้สร้างแอปพลิเคชันได้โดยไม่ต้องใช้ JavaScript มากนัก
- มีเป้าหมายเพื่อให้โหลดหน้าแรกได้เร็ว คงการเรนเดอร์เทมเพลตฝั่งเซิร์ฟเวอร์ไว้ และให้ประสบการณ์การพัฒนาที่เรียบง่ายและมีประสิทธิภาพมากขึ้น
- เป็นทิศทางที่ไม่ยอมทิ้งความเร็วและการตอบสนองที่คาดหวังจากแอปพลิเคชันหน้าเดียวแบบดั้งเดิม
- HTML-over-the-wire อาจใช้เป็นแนวทางอ้างอิงสำหรับสร้างเครื่องมือของตนเอง หรือจะใช้เฟรมเวิร์ก Hotwire ที่ 37signals สร้างขึ้นเพื่อ HEY โดยตรงก็ได้
บทบาทของ Turbo, Stimulus และ Hotwire Native
- Turbo เป็นองค์ประกอบหลักของ Hotwire
- ให้เทคนิคเสริมสำหรับจัดการการเปลี่ยนหน้าและการส่งฟอร์มอย่างรวดเร็ว
- แบ่งหน้าที่ซับซ้อนออกเป็นคอมโพเนนต์ และสตรีมการอัปเดตบางส่วนของหน้าผ่าน WebSocket
- ให้ความสามารถเหล่านี้โดยไม่ต้องเขียน JavaScript
- Stimulus ใช้เมื่อต้องการโค้ดแบบปรับแต่งเองที่ Turbo เพียงอย่างเดียวไม่เพียงพอ
- โดยทั่วไป Turbo จัดการการโต้ตอบที่แต่เดิมต้องใช้ JavaScript ได้อย่างน้อย 80%
- Stimulus ช่วยให้จัดการสถานะและการเชื่อมต่อด้วยแนวทางที่มี HTML เป็นศูนย์กลางได้
- Hotwire Native เป็นเฟรมเวิร์กแบบ web-first สำหรับสร้างแอปมือถือแบบเนทีฟ
- ให้เครื่องมือที่จำเป็นสำหรับสร้างแอปมือถือโดยใช้ประโยชน์จากเว็บแอปเดิม
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
มีเวอร์ชันที่ทำการตลาดน้อยกว่าของฟีเจอร์นี้อยู่คือ htmx: https://htmx.org/
มันทำให้ฟีเจอร์แบบนี้เป็นไปได้ด้วยไฟล์ JavaScript ไฟล์เดียว และถึงผมจะเห็นว่ามักใช้กับแบ็กเอนด์ Go เป็นหลัก แต่ก็ดูค่อนข้างยืดหยุ่น คิดว่าจะลองใช้มาตั้งแต่ราว ๆ 1 ปีก่อน
แค่ในปีที่ผ่านมาก็มีการส่งขึ้น HN หลายร้อยรายการ 0 และมีโพสต์ที่ได้เกิน 1,000 คะแนนด้วย ในทางกลับกัน Hotwire ในปีที่ผ่านมามีการส่งไม่ถึง 30 รายการ 1 และรายการที่ได้รับความนิยมที่สุดในนั้นก็คือบทความนี้
แค่เปิด YouTube ดูแป๊บเดียวก็เห็นอินฟลูเอนเซอร์สายโปรแกรมเมอร์ดัน htmx พร้อมภาพหน้าตัวเองบน thumbnail กันไม่หยุดแล้ว
Twitter ก็เคลื่อนไหวมาก และยังปรากฏบ่อยในช่อง YouTube ของ The Primeagen แถมค่อนข้างได้รับความนิยม
ถ้ากำลังมองหาสิ่งคล้ายกันใน PHP/Laravel ขอแนะนำ Livewire อย่างแรง: https://laravel-livewire.com/
สำหรับโปรเจกต์ที่ซับซ้อนกว่านี้ก็ยังใช้ React อยู่ แต่การเขียนทุกอย่างด้วย Blade/PHP ขณะยังคงมีองค์ประกอบ UI แบบตอบสนองได้เป็นเรื่องที่รู้สึกสดใหม่เสมอ จำได้ว่าเคยเห็นแพ็กเกจที่ช่วยให้เรนเดอร์คอมโพเนนต์ React/Vue ภายใน Livewire ได้เมื่อจำเป็นด้วย: https://minglejs.unitedbycode.com/. ดูเหมือนเป็นทางออกที่น่าสนใจเมื่อจำเป็นต้องดึงแพ็กเกจเดิมมาใช้
เมื่อก่อนค่อนข้างมอง Hotwire/Livewire ในแง่ลบ แต่ตอนนี้มองว่าเป็น เครื่องมือที่เหมาะกับบางสถานการณ์
การส่ง partial template ผ่าน wire เป็นแนวทางแบบไฮเปอร์มีเดีย เพียงแต่ทุกวันนี้เราไม่ค่อยสร้างแอปไฮเปอร์มีเดียดี ๆ กันเท่านั้นเอง ผมมาถึงจุดนี้หลังจากกลับไปอ่าน htmx และบทความ REST ของ RTF อีกครั้ง และถึงจะไม่ได้มองว่าไฮเปอร์มีเดียเป็นสถาปัตยกรรมที่เหนือกว่าโดยเนื้อแท้ แต่มันก็เป็นเพื่อนร่วมทางที่ชอบธรรมในบรรดาตัวเลือกหลาย ๆ แบบ และก็ดีที่มันยังค่อย ๆ วิวัฒน์ต่อไปแม้จะช้า
น่าจะใกล้เคียงกับวิธีที่ง่ายที่สุดในการสร้าง PWA โดยไม่ต้องหลุดเข้าไปในโพรงกระต่ายของ React/Vue/Svelte
ผมก็เคยใช้พวกนั้นมาแล้วและคิดว่ามันยอดเยี่ยม แต่เมื่อเทียบกับ htmx แล้วรู้สึกเหมือนเน้นประสบการณ์นักพัฒนามากกว่าเน้นเทคโนโลยี สุดท้ายการแข่งขันระหว่างสองฝั่งคงขึ้นอยู่กับว่าฝั่งไหนผสานกับแบ็กเอนด์เฟรมเวิร์กได้ดีกว่ากัน
โดยส่วนตัวผมมองว่า PWA เป็นปัญหาฝั่งไคลเอนต์ และควรจัดการทางฝั่งไคลเอนต์โดยไม่เพิ่มการพึ่งพาฝั่งเซิร์ฟเวอร์
บทสนทนาใน HN ปี 2020 ซึ่งใกล้เคียงกับช่วงที่สิ่งนี้ออกมาครั้งแรกกว่าอยู่ที่นี่: https://news.ycombinator.com/item?id=25507942
บทความที่เกี่ยวข้องได้แก่ Why Hotwire Could be the Future of Front-end Dev - https://news.ycombinator.com/item?id=26195969 - กุมภาพันธ์ 2021, 6 ความคิดเห็น / Hotwire: A new old way to build web apps - https://news.ycombinator.com/item?id=25942864 - มกราคม 2021, 56 ความคิดเห็น
รู้สึกเหมือนวนกลับมาเกือบครบหนึ่งรอบแล้ว จำได้ว่าราวปี 2005 หรือ 2006 เคยใช้วิธีดักคลิกแล้วแนบพารามิเตอร์เข้าไป จากนั้นรับกลับมาเฉพาะ ชิ้นส่วน HTML ที่เรนเดอร์แล้ว แล้วใช้
.innerHTMLแทนที่เนื้อหาหลักเคล็ดลับคือเปิด HTTP request ค้างไว้ตลอด แล้วให้เซิร์ฟเวอร์ส่งอัปเดตมาเป็นครั้งคราว และอัปเดตนั้นก็เป็น HTML ด้วย ตอนนั้นอาจยังทำ DOM manipulation ไม่ได้ด้วยซ้ำ จึงอาจเป็นเพจที่มีแท็กที่ไม่ถูกปิดอยู่จริง ๆ ก็ได้
เฟรมเวิร์กแบบ server rendering กำลังทำให้การโต้ตอบบนไคลเอนต์ง่ายขึ้น ส่วน React ก็ทำให้ server rendering ง่ายขึ้นผ่าน RSC ถ้าเป็นเว็บแอปที่มีการโต้ตอบสูงมาก SPA ก็ยังได้เปรียบอยู่
โปรเจกต์ SPA มีเยอะมากก็จริง แต่นั่นไม่ได้อธิบายเว็บไซต์ทั้งหมดในโลก
pagination ทำโดยเมื่อเลื่อนลงแล้วกด “Show more” ก็จะขอหน้าถัดไปจากเซิร์ฟเวอร์เป็นชิ้นส่วน HTML โหลดเข้า iframe ที่มองไม่เห็น แล้วเมื่อโหลดเสร็จก็นำมาต่อท้ายหน้าปัจจุบัน
เมื่อคิดว่าระหว่างนั้นเว็บ, JavaScript และ TypeScript ดีขึ้นมากแล้ว ก็ยากที่จะตื่นเต้นกับแนวทางนี้อีกครั้ง
ยังไม่เคยทำเว็บแอปที่ต้องการฟรอนต์เอนด์แบบโต้ตอบขั้นสูงมากนัก แต่ในร้านค้าอีคอมเมิร์ซและแอป Rails ภายในองค์กร Turbo และ Stimulus ช่วยลดสิ่งที่นักพัฒนาใหม่ต้องเรียนรู้ลงได้มาก
เช่น ในโปรเจกต์ Django หนึ่ง เคยใช้ KnockoutJS ที่ผ่านการพิสูจน์แล้วสร้างเครื่องมือสำหรับใช้ในออฟฟิศทั้งชุดได้อย่างรวดเร็ว และสิ่งนี้ก็สอดคล้องกับจิตวิญญาณของ HTMX อยู่บ้าง Arrow.JS ที่ยังอยู่ช่วงต้นก็คล้ายกัน ความซับซ้อน โดยเฉพาะความซับซ้อนฝั่ง UI ส่วนใหญ่มักเป็นสิ่งที่เราสร้างขึ้นเอง วิธีเก่า ๆ ไม่ได้ล้าสมัยเลย และกำลังกลับมาด้วยซ้ำ มีนักพัฒนารุ่นใหม่กลุ่มหนึ่งที่เข้าวงการมาในช่วงที่โง่เขลาที่สุด ซึ่งอุตสาหกรรมพยายามโน้มน้าวว่าทุกเว็บแอปพลิเคชันต้องถูกทำให้ซับซ้อนเกินจำเป็นและกลายเป็นก้อนที่ทนดูแลแทบไม่ได้
ใช้ Hey แบบเสียเงินมาตั้งแต่เปิดตัว ถ้าประสบการณ์เว็บแอป Hey คือ กรณีตัวอย่างที่ดีที่สุดของ Hotwire ผมขอผ่าน
บนการเชื่อมต่อที่ช้า มันแย่ อาจเป็นเพราะนักพัฒนาไม่ได้ใส่สถานะโหลดหรือสถานะข้อผิดพลาด อาจเป็นเพราะความซับซ้อนสูง หรืออาจเป็นบั๊กของ Hey ก็ได้ ไม่รู้เหมือนกัน แต่ไม่ดีแน่
เมื่อ latency อยู่ระดับกลางถึงสูง พฤติกรรมจะคาดเดาไม่ได้หรือรู้สึกเหมือนมีบั๊ก มีกล่องเปล่าเปิดขึ้นมา ลิงก์ไม่ทำงานอย่างที่คาด และเมื่อทำหลายอย่างต่อเนื่องอย่างรวดเร็ว มันก็ไม่ถูกยกเลิกในแบบที่เป็นธรรมชาติ รู้สึกเหมือนทุกอย่างเหลื่อมกันไปหมด
ต่อให้ SPA จะแย่แค่ไหน แต่นี่เหมือนเป็นการถอยห่างไปอีกก้าวจากทิศทางที่ UI ให้ความรู้สึกเป็น native และเป็นธรรมชาติ
เหตุผลที่บทความนี้กลับมาถูกพูดถึงตอนนี้ คือสัปดาห์ที่แล้วมีคนโพสต์ว่า Hey เปิด modal ช้า: https://x.com/noahflk/status/1795758603577545035
Hey สร้างโดย DHH และ DHH ก็เป็นคนสร้าง Hotwire กับ Rails ด้วย จากนั้นก็กลายเป็นการถกเถียงร้อนแรงปนกันไป ทั้งคำโต้แย้งของ DHH ว่าวิดีโอต้นฉบับถ่ายบนเครือข่ายที่ถูกจำกัด, ปฏิกิริยาว่าถ้าโหลด modal ต้องใช้เวลา แปลว่า Hotwire พึ่งพาเครือข่ายมากเกินไป, การปกป้อง Rails/Hotwire และการคัดค้านแนวทางนี้ เรื่องนี้เป็นประเด็นใหญ่บน Twitter เมื่อสัปดาห์ที่แล้ว
ผู้เขียนเองก็เขียนว่า “ตั้งใจทำให้ช้าเพื่อการสาธิต”: https://x.com/noahflk/status/1795855075526471915 เขาบอกว่าไม่ได้ต้องการแสดงประสบการณ์ของคนที่ใช้ “MacBook ดี ๆ ใน SF กับอินเทอร์เน็ตกิกะบิต” แต่หมายถึงคนที่ใช้อินเทอร์เน็ตมือถือช้าและแล็ปท็อปราคาถูก นอกจากนี้ยังมีคนชี้ว่า Google Calendar SPA ช้ากว่ามาก และตัวเลือกก็ไม่ได้มีแค่ “อินเทอร์เน็ตกิกะบิตใน SF” กับ “3G ที่ถูกจำกัดอย่างหนัก” เท่านั้น โพสต์ต้นฉบับชวนให้เข้าใจผิดอย่างมาก และแทบจะใกล้เคียงกับการโกหก
โดยเฉพาะโครงสร้างหน้าที่น่าประทับใจมาก เช่น overlay ของ context menu ใช้การผสม
details/summary/anchorแบบ progressive enhancement และแม้จะปิด JavaScript หรือ asset โหลดไม่ขึ้น ก็ยังโหลดเนื้อหาเมนูอย่างสง่างามในเลย์เอาต์แบบเรียบง่ายได้ นอกจากนี้ยังมีหลายจุดที่ใช้ Web API อย่างระมัดระวัง และเท่าที่จำได้ โค้ดฝั่งไคลเอนต์แทบไม่ได้ถูก obfuscate และมี source map แนบมาด้วย ผมไม่ใช่แฟน DHH และไม่ได้ตั้งใจติดตามดราม่าสัปดาห์นั้น แต่ครั้งนี้รู้สึกว่า 37signals ทำได้ถูกทางแล้วเมื่อ 2 ปีก่อนผมเคยทำ Swap JS ซึ่งเป็นการนำแนวคิดเดียวกันไปใช้งานแบบมินิมอลกว่า: https://github.com/josephernest/Swap
เคยใช้ในบางโปรเจกต์แล้ว และทำงานได้ดี