Ruby on Rails ออกเวอร์ชันใหญ่ 7.0 ซึ่งมีการเปลี่ยนแปลงสำคัญ 2 เรื่องคือ ไม่ต้องผูกกับโลกของ Node.js อีกแล้ว และเปลี่ยนระบบ front-end มาเป็นตัวใหม่คือ Hotwire
David Heinemeier Hansson หรือ DHH ผู้สร้าง Rails อธิบายว่าโครงสร้างของภาษา JavaScript ในอดีตเป็นปัญหาของโปรแกรมเมอร์มาก ทางออกจึงเป็นการเขียนภาษาอื่นแล้วแปลงเป็น JavaScript (เรียกว่า transpiling เช่น CoffeeScript หรือ Babel) ที่ช่วยให้เขียนโค้ดง่ายขึ้น แต่ก็ต้องแลกมาด้วยความซับซ้อนที่เพิ่มขึ้น
แนวทางของ Rails ช่วงก่อนหน้านี้คือใช้ Webpack (ผ่าน Webpacker) เป็นตัวช่วย bundler โมดูล JavaScript ต่างๆ เข้าด้วยกัน โดยเริ่มจาก Rails 5.2 ในปี 2017 ข้อเสียของแนวทางนี้คือ Webpack โยงอยู่กับ Node.js จึงทำให้ Rails ต้องเรียกใช้ Node.js ตามไปด้วย
แต่เมื่อเวลาผ่านมา 5 ปี สถานการณ์เปลี่ยนไปมาก เพราะเว็บเบราว์เซอร์ทุกตัวรองรับภาษา ECMAScript 6 (ES6) ที่เปลี่ยนโครงสร้างของ JavaScript ไปมากแล้ว (เหลือแต่ IE11 และไมโครซอฟท์ก็ฆ่าทิ้งเรียบร้อยแล้ว) ทำให้เราสามารถเขียนโค้ด ES6 ตรงๆ ได้เลย
เทคโนโลยีอีกตัวที่เปลี่ยนโลกของการพัฒนาเว็บคือ HTTP2 ที่หนึ่งการเชื่อมต่อสามารถส่งไฟล์ได้หลายไฟล์พร้อมกัน ทำให้การมัดรวมไฟล์ JavaScript เป็นไฟล์เดียวไม่มีประโยชน์เพิ่มขึ้นมากเหมือนในอดีต เราจึงไม่ต้องมี bundler อีกแล้ว เพราะเสียเวลาประมวลผล และแก้ไขข้อมูลภายหลังได้ยาก
เทคโนโลยีตัวที่สามคือ import maps ซึ่งเปลี่ยนวิธีการอิมพอร์ตไฟล์ JavaScript จากการระบุชื่อไฟล์ตรงๆ (ถ้าไฟล์เปลี่ยนชื่อ ต้องจัดการแคชของเบราว์เซอร์ใหม่) มาเป็นการ mapping แทนซึ่งเป็น logical มีความยืดหยุ่นสูงกว่า (ฟีเจอร์นี้ใช้ได้แล้วกับเบราว์เซอร์ตระกูล Chromium)
เทคโนโลยีทั้งสามตัวทำให้ Rails ไม่จำเป็นต้องพึ่งพาเครื่องมือสาย JavaScript ที่ซับซ้อนอีกต่อไป สามารถเขียน JavaScript (ES6) ตรงๆ แล้วสื่อสารกับเบราว์เซอร์ได้เลย การเปลี่ยนแปลงสำคัญของ Rails 7.0 จึงเป็นการถอด Webpacker ออก (ทำให้ไม่จำเป็นต้องพึ่งพา Node.js) โดยยังสามารถใช้ bundler ได้ถ้าต้องการ และเลือกใช้ตัวใดก็ได้ไม่ว่าจะเป็น esbuild, rollup.js หรือแม้แต่ Webpack เหมือนเดิม เช่นเดียวกับ CSS bundler ที่เลือกใช้ตัวใดก็ได้ เช่น Tailwind, Bootstrap, Sass, PostCSS โดยไม่ต้องผูกกับ Node.js
ส่วนฝั่ง front-end เปลี่ยนมาใช้ Hotwire ซึ่งพัฒนาโดยบริษัท Basecamp เช่นกัน แนวคิดของ Hotwire คือส่งข้อมูลไปยังเบราว์เซอร์เป็น HTML แทน JSON (HTML-over-the-wire) เพื่อให้การเรนเดอร์เทมเพลตอยู่ที่ฝั่งเซิร์ฟเวอร์ เพจโหลดเร็วขึ้น และลดความซับซ้อนลง ถูกนำมาใช้แทนระบบ front-end เดิมของ Rails ที่เป็น Turbolinks และ Rails UJS
การเปลี่ยนแปลงทั้งสองส่วนทำให้ Rails 7 เรียบง่ายขึ้นกว่าเดิมมากๆ ซึ่ง DHH เชื่อว่านี่คือสิ่งที่การพัฒนาเว็บควรจะมุ่งไป และตอนนี้บริษัท Basecamp ของเขาก็พัฒนาเว็บเมล Hey ด้วยเฟรมเวิร์คตัวใหม่นี้อยู่
Comments
“ส่วนฝั่ง front-end เปลี่ยนมาใช้ Hotwire ซึ่งพัฒนาโดยบริษัท Basecamp เช่นกัน แนวคิดของ Hotwire คือส่งข้อมูลไปยังเบราว์เซอร์เป็น HTML แทน JSON (HTML-over-the-wire) เพื่อให้การเรนเดอร์เทมเพลตอยู่ที่ฝั่งเซิร์ฟเวอร์ เพจโหลดเร็วขึ้น”
โลกเว็บสมัยใหม่มัก render หน้าเว็บที่ฝั่ง client เพราะอ้างว่าเร็วกว่า render ที่ server
ไหงคราวนี้กลับกันล่ะ หรือผมเข้าใจอะไรผิดไป?
ทำไมผมได้ยินว่า ยังไง ssr (server-side rendering) ก็เร็วกว่า csr (client-side rendering)
ขึ้นกับว่าเราจะมองฝั่งไหน
ถ้ามองฝั่ง client พวก server-side เร็วกว่าแน่นอนเพราะ client ไม่ต้องทำหน้าที่ในการหยิบ element มาแยกต่อด้วย JavaScript แสดงข้อมูลตามที่ server บอกก็พอ
ถ้ามองฝั่ง server พวก client-side เร็วกว่าแน่นอนเพราะไม่ต้องประมวลผลส่วนประกอบของเว็บไซต์ก่อน ให้เป็นหน้าที่ของ client ไปจัดการต่อเอง
ผมเข้าใจว่า ความเร็วในที่นี้หมายถึงความเร็วในการแสดงหน้าเพจครั้งแรกนะครับ
ถ้าเป็น ssr ข้อมูลทั้งหมดจะพร้อมมาตั้งแต่ฝั่ง server ตัว browser สามารถแสดงผลได้เลย แต่ถ้าเป็น csr กว่าไฟล์ข้อมูลทั้งหมดจะส่งมาถึง แล้ว render อีก ถ้าไม่มี prefetch ต้องดูรูปภาพจากที่ render อีก มันเลยช้ากว่าฝั่ง ssr ครับ (http2 อาจจะทำให้ตรงนี้ดีขึ้น แต่ก็ไม่แน่ใจเท่าไหร่ครับ)
Jusci - Google Plus - Twitter
Webpack นั้นมันแค่ตัว bunble นะครับไม่ใช่ transpiler ตัว transpile น่ะคือ babel
และต่อให้เป็น HTTP2 แต่คุณส่ง file ใหญ่มันก็ช้าอยู่ดี bunble ส่งไปน่ะดีแล้ว
HTTP2 นี้ผมว่าจุดประสงค์หลักมันไม่ได้เพิ่อ client เลยนะ เพื่อ server จะได้ลด resource เอาไปจัดการ connection มากกว่า
js bundler มันคือการจับเอาไฟล์ไปต่อกันดื้อ ๆ เลย
ถ้ามองแค่แง่นี้ ใน HTTP 1.0 ทุกครั้งที่ส่งไฟล์ต้องต่อ connection ใหม่ ตรงนี้ overhead จะสูงมาก พอใช้ bundler มันเลยได้เปรียบกว่าเพราะส่งแค่ไฟล์เดียว แต่พอเป็น HTTP2 มันส่งใน connection เดียวกันตลอด ทำให้ overhead ตรงนี้หายไป
แต่การส่งหลายไฟล์มันก็ยังมี overhead อยู่ ซึ่งเค้าก็เปิดช่องให้ใช้ bundler ได้อยู่ถ้า dev concern ตรงนี้ครับ
น่าจะประมาณนี้มั้ง
เออใช่มันเอาไฟล์มาต่อกันแค่นั้น ผมใช้ minify transform มันตลอดจนลืมไปเลย