- การอภิปรายที่เปรียบเทียบ Backbone ในช่วงต้นทศวรรษ 2010 กับ React ในปี 2025 เพื่อย้อนดูว่าพัฒนาการของฟรอนต์เอนด์ตลอด 15 ปีที่ผ่านมา ก้าวหน้าไปมากน้อยเพียงใดจริง ๆ
- React ดู กระชับและทันสมัย จากภายนอก แต่ภายในกลับอาศัย ชั้นของ abstraction ที่ซับซ้อนเพื่อสร้างภาพลวงของความเรียบง่าย
- Backbone แม้โค้ดจะยืดยาวกว่า แต่ ลำดับการไหลของอีเวนต์และการจัดการ DOM ชัดเจน ทำให้นักพัฒนามือใหม่ก็สามารถไล่ตามการทำงานได้ง่าย
- React มีโครงสร้างที่ทำให้ดีบักได้ยาก หากไม่เข้าใจการทำงานภายใน เช่น state management, dependency array, ปัญหา closure
- ท้ายที่สุด บทความชวนให้ย้อนคิดถึงแก่นแท้ว่า “อีเวนต์ + สถานะ = UI” พร้อมตั้งคำถามถึงความจำเป็นของโมเดลใหม่ที่เรียบง่ายและ hackable
ความก้าวหน้าตลอด 15 ปี
- ตัวอย่างช่องกรอกรหัสผ่านที่เขียนด้วย เฟรมเวิร์กยุค 2010s (Backbone) และอีกอันด้วย React ที่พัฒนามานานกว่า 10 ปี
- โค้ดทั้งสองชุดมีความยาวใกล้เคียงกันและทำงานเหมือนกัน
- React ได้รับการสนับสนุนจากเวลาของนักพัฒนาจำนวนมหาศาลและ ecosystem ขนาดใหญ่
- แต่ผู้เขียนชี้ว่า สิ่งที่น่าสนใจกว่า “React ดีขึ้นแค่ไหน” คือ “มันพัฒนาไปน้อยแค่ไหน”
- React มอบ ภาพลวงของความเรียบง่ายภายนอก แต่ในความเป็นจริงกลับเข้าใจยากขึ้นเพราะ abstraction ที่ซับซ้อน
- Backbone แสดงลำดับที่เรียบง่ายอย่างชัดเจน: เกิดอีเวนต์ → รัน handler → สร้าง HTML → แทรกลง DOM
- ขณะที่ React ซ่อนการทำงานภายในไว้ และเมื่อเลยจากตัวอย่างง่าย ๆ ไปแล้ว ก็มักเกิด ปัญหาที่แก้ได้ก็ต่อเมื่อเข้าใจกลไกภายในเท่านั้น
ภาพลวงของความเรียบง่าย (The Illusion of Simplicity)
- React ทำให้โค้ดดูสะอาดตา แต่สิ่งนี้เป็นผลจากการเลือก ความซับซ้อนเชิงนามธรรมแทนความเรียบง่ายแบบชัดแจ้ง
- Backbone แม้จะยืดยาว แต่แสดงให้เห็นชัดว่า “เกิดอะไรขึ้น เมื่อไร”
- แม้นักพัฒนามือใหม่ก็ยังตามลำดับของโค้ดได้ง่าย
- ใน React สถานะภายในและตรรกะการเรนเดอร์ถูกซ่อนไว้ จึงเกิด บั๊กที่ไม่คาดคิด ได้บ่อย
- ตัวอย่าง: ถ้าเปลี่ยน key ของรายการในลิสต์เป็น index, React อาจมองว่าเป็นคอมโพเนนต์คนละตัวและรีเซ็ต state
- หาก
value เปลี่ยนเป็น undefined จะเกิดการเปลี่ยนจาก uncontrolled → controlled component ทำให้ค่าที่พิมพ์ไว้ถูกรีเซ็ต
- ปัญหา ลูปไม่รู้จบ เมื่อใช้
useEffect ก็พบได้บ่อย
- ถ้า dependency array มีอ็อบเจ็กต์ที่ถูกสร้างใหม่ทุกครั้งที่เรนเดอร์ React จะมองว่ามีการเปลี่ยนแปลง
- เพื่อป้องกันสิ่งนี้ จึงต้องใช้
useMemo, useCallback เพื่อ ทำให้ identity คงที่ (stabilize identities)
- กลายเป็นภาระที่ต้องใส่ใจกับแนวคิดที่เมื่อก่อนอาจไม่จำเป็นต้องคิดถึง
- ยังมีปัญหาที่ click handler ไปอ้างอิง สถานะเก่า (stale state)
- เพราะฟังก์ชันจะจับค่า state ณ เวลาที่มันถูกสร้างขึ้นมา
- วิธีแก้คือใส่ state ลงใน dependency array หรือใช้ functional update เช่น
setState(x => x + 1)
- แต่ทั้งสองแนวทางก็ยังให้ความรู้สึกเหมือนเป็น วิธีอ้อมแก้ปัญหา (workaround)
ราคาของเวทมนตร์ (Magic Has a High Price)
- ปัญหาเหล่านี้ไม่ใช่กรณียกเว้น แต่เป็น ปัญหาทั่วไปที่เกิดบ่อยในแอประดับกลางขึ้นไป
- การดีบักต้องเข้าใจ reconciliation algorithm, render phase, scheduler (batch update)
- React เป็นโครงสร้างแบบ “ไม่ต้องรู้ว่าทำไมมันถึงทำงาน มันก็ทำงานได้” แต่ เมื่อมีปัญหา ก็ต้องรู้ข้างในถึงจะแก้ได้
- ความซับซ้อนถึงขั้นมีคำพูดว่า “ถ้าอยากเข้าใจ React จริง ๆ ต้องลองสร้างมันเอง”
- มีทิวทอเรียลอย่าง “Build your own React”
- แต่การที่ต้องเข้าใจ virtual DOM, scheduling priority, concurrent rendering เพียงเพื่อสร้าง ตัวตรวจสอบรหัสผ่าน แบบง่าย ๆ ก็เป็น นัยเชิงวิพากษ์ ที่ชัดเจน
- Backbone และ jQuery มีโครงสร้างที่ ตรงไปตรงมาและ hackable
- สามารถเปิดซอร์สโค้ดดูและแก้ไขได้โดยตรง
- ด้วยการอิงเมธอดของ DOM จึงเข้าใจและต่อยอดได้ง่าย
- ขณะที่ ชั้น abstraction ของ React ทำให้เข้าถึงและแก้ไขภายในได้ยาก
ขั้นต่อไปคืออะไร (So, What's Next?)
- สุดท้ายแล้ว ทั้ง React และ Backbone ต่างก็เป็นความพยายามในการแก้ปัญหาเดียวกันคือ “อีเวนต์ + สถานะ = UI”
- ในแอปขนาดใหญ่ ความซับซ้อนของ React อาจสมเหตุสมผล แต่สำหรับ แอปขนาดเล็กถึงกลางส่วนใหญ่ มันเป็นภาระที่มากเกินไป
- จึงจำเป็นต้องมี โมเดล UI ใหม่ ที่ทั้งเรียบง่ายและโปร่งใส
- ระบบที่แข็งแรงเหมือน DOM แต่เข้าใจได้โดยสัญชาตญาณ
- มุ่งไปสู่โครงสร้างที่ เข้าใจและแก้ไขได้ทันที แบบ Backbone หรือ jQuery
2 ความคิดเห็น
สำหรับแอประดับเล็กถึงกลาง ผมคิดว่าการออกแบบ JavaScript Class น่าจะเป็นท่าทีที่เตรียมพร้อมสำหรับยุคถัดไปมากกว่าการใช้ Backbone หรือ jQuery
การกลับไปท่องจำเทมเพลตใน jQuery หรือ Backbone แล้วพัฒนาต่อ ดูเหมือนเป็นการถอยหลังมากกว่า
ความคิดเห็นใน Hacker News
เคยใช้ทั้ง Backbone, Angular 1, Ember และ React
ไม่ควรมองข้ามเหตุผลที่ React ได้รับความนิยม React แก้ปัญหาเรื้อรังของเฟรมเวิร์กยุคก่อนในด้าน การประกอบคอมโพเนนต์, การจัดการอีเวนต์, การจัดการสถานะ, และ การอัปเดต DOM อย่างมีประสิทธิภาพ
Backbone จัดการวงจรชีวิตของ DOM ได้ซับซ้อน และต้องกำหนด event handler เป็นสตริง ทำให้ดูแลรักษายาก React ทำให้ปัญหาเหล่านี้ง่ายขึ้นด้วยการไหลของสถานะแบบทางเดียวและ virtual DOM
ถ้าตอนนี้อยากใช้ JS ล้วน คิดว่าโซลูชันเทมเพลตอย่าง lit-html ดีกว่า Backbone มาก
ฟรอนต์เอนด์เมื่อก่อนก็ซับซ้อนและตอนนี้ก็ยังซับซ้อนอยู่ แต่ ตอนนี้เจ็บปวดน้อยกว่ามาก
ความซับซ้อนของแอปไม่ได้มาจากจำนวนคอมโพเนนต์ แต่มาจาก การจัดการสถานะ
เคยเจอปัญหา UI ค้างบ่อยมากเพราะการไหลของข้อมูลแบบสองทางใน Backbone Store นวัตกรรมของ React คือสถาปัตยกรรม Flux ที่มี การไหลของข้อมูลแบบทางเดียว เป็นศูนย์กลาง
คิดว่าเฟรมเวิร์กที่ดีคือเครื่องมือที่พาเราเข้าสู่ “หลุมแห่งความสำเร็จ (Pit of Success)” ได้อย่างเป็นธรรมชาติ และ React ก็ทำหน้าที่นั้นได้ดี
ตัวอย่างเช่นปัญหาอย่าง stale closure, ลูป useEffect ไม่สิ้นสุด, และ การรีเซ็ตค่าอินพุตเพราะเปลี่ยน key เป็นสิ่งที่ Backbone ไม่มี
ปัญหาของ Backbone มองเห็นได้ตรง ๆ และดีบักง่าย แต่ปัญหาของ React ซ่อนอยู่หลังชั้นนามธรรม
แอปส่วนใหญ่ไม่ได้มีขนาดระดับ Facebook ดังนั้นแนวทางที่ชัดเจนและเรียบง่ายอาจดีกว่าก็ได้
การตัดสินว่าเทคโนโลยีที่ได้รับความนิยมว่า “แย่” ดูเป็น ความหยิ่งผยองแบบไร้เดียงสา อย่างหนึ่ง
แน่นอนว่าความนิยมไม่ได้รับประกันคุณภาพ แต่การมองว่าวิศวกรเก่ง ๆ ทั่วโลกถูกหลอกกันหมดก็มากเกินไป
ถ้าบริษัทใหญ่กับการตลาดช่วยผลักดัน CTO ก็จะรับไปใช้ และเมื่ออาชีพผูกอยู่กับมัน ก็ไม่มีใครอยากพูดว่า “อันนี้ไม่ค่อยดี” ความนิยม ≠ ความเหมาะสม
React ไม่ได้ชนะเพราะความเหนือกว่าทางเทคนิคเพียงอย่างเดียว แต่ยังเพราะ การตลาดของ Facebook และการเสริมแรงกันเองของระบบนิเวศ ด้วย
ผ่านมา 15 ปี ความยาวและความซับซ้อนของโค้ดก็ไม่ได้ลดลงมากนัก แค่ ซับซ้อนในอีกแบบหนึ่งเท่านั้น
การย้อนมองอดีตไม่ใช่เพราะความคิดถึง แต่เพื่อทบทวนว่าเราได้เพิ่ม ความซับซ้อนที่ไม่สมส่วน เข้าไปหรือไม่
เว็บยังคงเหมือน แดนเถื่อนของ design pattern พอยอมรับจุดนั้นได้ก็รู้สึกสบายใจขึ้น
สุดท้ายแต่ละโปรเจกต์ก็ต้อง ประเมิน trade-off ใหม่
คำกล่าวที่ว่า “งานง่าย ๆ ไม่ต้องใช้ React” เป็น React fallacy แบบที่เจอบ่อย
การประเมิน React จากตัวอย่างง่าย ๆ ก็เหมือน “ประเมินภาษาจากความยาวของ Hello World”
เหตุผลที่ใช้ React กับงานง่ายก็เพราะมันถูกใช้กับงานยากด้วย ชุดเครื่องมือที่สม่ำเสมอ ช่วยเรื่องการดูแลรักษาได้
Backbone เป็น “สิ่งที่ดูเหมือนเฟรมเวิร์ก แต่จริง ๆ แล้วเป็นกองโค้ดกาว”
ชัยชนะที่แท้จริงของ React คือ ไม่ต้องจัดการ DOM โดยตรง และสามารถทำ การจัดการสถานะแบบ reactive ได้ สองอย่างนี้ช่วยเพิ่มผลิตภาพของนักพัฒนาอย่างมาก
ลิงก์บทเรียนเก่า, เวอร์ชัน archive
ทุกวันนี้สนใจมากกว่าว่า LLM เข้าใจโค้ดอย่างไร ไวยากรณ์เชิงประกาศอย่าง JSX เป็นมิตรกับ LLM
แต่ React หลังยุค useEffect กลับให้ความรู้สึกว่ามัวลงในแง่ พลังในการแสดงออกและความชัดเจน
เห็นได้ชัดว่าทำไม React ถึงได้รับความนิยม
โค้ด React ส่วนใหญ่เป็น JS และ HTML ล้วน และหัวใจสำคัญมีเพียง
useStateตัวเดียว มันเข้าใจได้ตรงไปตรงมาจนแทบไม่ต้องอ่านเอกสารBackbone พึ่งพาสตริงเซเลกเตอร์อย่าง
.space-y-2จนการดูแลรักษากลายเป็นนรก เปลี่ยนชื่อคลาสทีเดียวแอปพังไปครึ่งหนึ่งReact แก้ปัญหาแบบนี้ได้ในเชิงโครงสร้าง
โค้ด Backbone ชัดเจนว่า “อะไรเกิดขึ้น เมื่อไหร่” แต่ React ต้องเข้าใจการทำงานภายในของมัน
ผมเองก็ต้องอ่าน คู่มือ useEffect ของ Dan Abramov กับ บล็อกของ Mark Erikson หลายรอบกว่าจะเข้าใจจังหวะการทำงานของ React
โค้ด Backbone ต่อให้กลับมาดูอีกครั้งหลังผ่านไป 10 ปีก็ยังเข้าใจได้ทันที
เมื่อ 6 ปีก่อนย้ายทีมจาก Backbone ไป Angular
Backbone มีโครงสร้างที่ ตรงไปตรงมาและไม่มีเวทมนตร์ จึงเหมาะกับจูเนียร์ แต่ท้ายที่สุด TypeScript และ Angular ก็เป็นระบบระเบียบมากกว่า
ตอนนี้ใช้ NG20 อยู่และพอใจดี วันหนึ่งถ้าเบราว์เซอร์มีความสามารถพื้นฐานเพิ่มขึ้นมากกว่านี้ ก็อาจกลับไปสู่แนวทางที่เรียบง่ายอีกครั้ง
เรากำลัง เขียนโปรแกรมอยู่บนชั้นนามธรรม กันเสมอ
สิ่งสำคัญคือชั้นนามธรรมนั้นให้ ผลตอบแทนด้านผลิตภาพคุ้มกับความซับซ้อนหรือไม่ และ เชื่อถือได้หรือไม่
อย่างน้อยในกรณีเลวร้ายที่สุด มันก็ควรยังดีบักได้
ฟิลด์อินพุตของ React จัดการ พฤติกรรม Undo ได้เป็นธรรมชาติกว่า Backbone
Backbone ย้อนกลับทีละตัวอักษร แต่ React ย้อนกลับเป็นคำ