1 คะแนน โดย GN⁺ 2025-06-28 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • แม้เว็บแพลตฟอร์มจะกลายเป็นรันไทม์สำหรับแอปพลิเคชันแบบไดนามิกแล้ว แต่ DOM มาตรฐานยังไม่มี Declarative Templating API ที่จัดการข้อมูล อีเวนต์ พร็อพเพอร์ตี การป้องกัน XSS และการอัปเดตอย่างมีประสิทธิภาพได้พร้อมกัน
  • เฟรมเวิร์กสมัยใหม่อย่าง React, Vue, Angular, Lit, Svelte และ SolidJS ใช้ ระบบเทมเพลต ที่ผสานมาร์กอัปกับข้อมูลเป็นแกนหลัก ซึ่งส่งผลต่อความอ่านง่าย ความปลอดภัย ประสิทธิภาพ การวิเคราะห์แบบสแตติก และ server-side rendering
  • ในอดีต E4X, E4H และแท็ก template literal html แบบ built-in ช่วยเรื่องการสร้าง DOM ได้ แต่แก้ปัญหา การอัปเดต DOM ไม่ได้ และตอนนี้ tagged template literals กับประสบการณ์จากเฟรมเวิร์กได้ให้พื้นฐานสำหรับการทำให้เป็นมาตรฐานแล้ว
  • API ที่ใช้ JavaScript มีขอบเขตเล็กกว่าการทำ JSX ให้เป็นมาตรฐานหรือเทมเพลตที่ใช้ HTML และเมื่อกลายเป็น เป้าหมายการคอมไพล์ ของการแปลง JSX ก็สามารถต่อยอดไปสู่ HTML templates และ declarative custom elements ได้ในภายหลัง
  • แนวทางที่เสนอเชื่อมโยงกับกลไกระดับล่างอย่าง DOM Parts, template identity, Signals และ DOM scheduler และอาจให้ฐานร่วมแก่ผู้พัฒนาแบบ vanilla ผู้ใช้ Web Components และผู้สร้างเฟรมเวิร์ก

ชั้น declarative templating ที่ไม่มีใน DOM มาตรฐาน

  • เว็บแพลตฟอร์มเป็นรันไทม์แอปพลิเคชันที่ประสบความสำเร็จที่สุดในประวัติศาสตร์ และ DOM API คือรากฐานที่เปลี่ยนตัวดูเอกสารแบบสแตติกให้เป็นรันไทม์แบบไดนามิกและสื่อความได้สูง
  • แม้แต่แอปซับซ้อนอย่าง Photoshop ก็ให้บริการเป็นเว็บแอปได้ และ DOM ก็เป็น API ที่ทรงพลังถึงขั้นที่ UI ทั้งหมดสามารถสร้างด้วย Web Components ได้
  • อย่างไรก็ตาม DOM API มาตรฐานในปัจจุบันยังไม่มีวิธีที่สะดวกในการจัดการงานต่อไปนี้ในคราวเดียว
    • สร้างชิ้นส่วนของ DOM nodes จากข้อมูล
    • เพิ่ม event listeners
    • ตั้งค่า properties ของ element
    • ทำให้ปลอดภัยจากการโจมตี XSS
    • อัปเดตชิ้นส่วน DOM นั้นอย่างมีประสิทธิภาพด้วยข้อมูลใหม่

คุณค่าของเทมเพลตที่เฟรมเวิร์กพิสูจน์แล้ว

  • เฟรมเวิร์กเว็บและไลบรารีเรนเดอร์สมัยใหม่ใช้เทมเพลตที่ ผสานมาร์กอัปกับข้อมูลแบบ declarative เป็นฟีเจอร์หลัก
    • รวมถึง React, Vue, Angular, Preact, Lit, Svelte, SolidJS, Stencil, Quik, Ember, FAST, Polymer, Marko และอื่นๆ
  • declarative templates เขียนและอ่านได้ดีกว่า DOM API แบบ imperative
    • interpolation, event listeners และการตั้งค่า properties อยู่ใกล้กับเทมเพลต ทำให้รักษา locality of behavior ได้ง่าย
  • ระบบเทมเพลตสามารถ escape ค่า interpolation โดยอัตโนมัติ จึงเป็นประโยชน์ต่อ การป้องกัน XSS
  • ระบบเทมเพลตที่ดีอาจเร็วกว่าโค้ดที่เขียนด้วยมือส่วนใหญ่ เพราะอัปเดตเฉพาะ DOM ที่จำเป็นต้องเปลี่ยน
  • ระบบเทมเพลตจำนวนมากรองรับ การวิเคราะห์แบบสแตติก เช่น type checking และ autocomplete
  • การตีความนิยาม declarative templates นอกสภาพแวดล้อมเบราว์เซอร์เต็มรูปแบบทำได้ จึงช่วยให้ทำ server-side rendering ได้อย่างมีประสิทธิภาพ

ต้นทุนที่เกิดจากการไม่มีเทมเพลต

  • แพลตฟอร์มยังไม่ตอบสนองความต้องการหลักของเว็บแอปพลิเคชันเกือบทั้งหมดโดยตรง
    • เทมเพลตก็ควรถูกมองเป็นฟีเจอร์มาตรฐานของแพลตฟอร์มได้ เช่นเดียวกับ internationalization API, Temporal, Scheduler และ Sanitizer
  • ผู้ใช้ได้รับผลกระทบจากเวลาโหลดแอป overhead ในการเรนเดอร์ และแอปที่ความปลอดภัยอ่อน
    • โค้ดไลบรารีเทมเพลตในกรณีดีที่สุดอาจมีขนาดไม่กี่ kB และในกรณีแย่ที่สุดอาจ เกิน 100kB
    • แม้ไม่กี่ kB ก็อาจเป็นสัดส่วนใหญ่ในงบประมาณการเรนเดอร์ครั้งแรกที่โต้ตอบได้
  • นักพัฒนาต้องพึ่งพาไลบรารี, npm และ CDN แม้กับงานพื้นฐาน
    • ประโยชน์ของไฟล์สแตติกเรียบง่ายและ DevTools ลดลง
    • ไม่มีความรู้พื้นฐานเรื่องเทมเพลตที่พกพาข้ามสแตกได้
    • API สร้าง DOM แบบ native อย่าง innerHTML โดยพื้นฐานแล้วไม่ปลอดภัย
  • เฟรมเวิร์กและไลบรารีเทมเพลตต้องประนีประนอมอย่างยากลำบากระหว่างความง่ายในการเขียน ความเร็วการเรนเดอร์ ความเร็วการอัปเดต ความปลอดภัย และขนาดโค้ด
  • เว็บแพลตฟอร์มแข่งขันกับแพลตฟอร์ม native อย่าง Flutter, SwiftUI และ Jetpack Compose
    • แพลตฟอร์มเหล่านี้มีระบบคล้ายเทมเพลตในตัว ใช้การติดตั้งแอปและภาษาที่คอมไพล์ และอ่อนไหวต่อขนาด bundle ไม่กี่ kB น้อยกว่า

เหตุผลที่ตอนนี้ลองอีกครั้งได้

  • ในอดีตก็เคยมีข้อเสนอระดับแพลตฟอร์มที่ใกล้เคียงกับเทมเพลต
    • E4X เคยถูกใส่จริงใน Firefox และ Flash
    • E4H เป็นแนวคิดที่ Ian Hixie ทำให้เรียบง่ายลง
    • ราวปี 2012 ก็มีต้นแบบแท็ก template literal html แบบ built-in
  • ความพยายามในอดีตช่วยเรื่องการสร้าง DOM แต่เพราะไม่ได้แก้ การอัปเดต จึงยากที่จะเป็นคำตอบที่เพียงพอ
  • ตอนนี้เฟรมเวิร์กได้สร้าง use cases ไว้มากพอแล้ว และโซลูชันเทมเพลตใน userland ก็คล้ายกันมากขึ้นเมื่อเวลาผ่านไป
  • ทั้งนักพัฒนาที่ไม่ใช้เฟรมเวิร์กและชุมชน Web Components ต่างก็มีความต้องการ API สำหรับจัดการ DOM และ reactivity ที่สะดวก
  • ข้อเสนอ primitives ระดับต่ำสำหรับอัปเดต DOM อย่าง DOM Parts กำลังเดินหน้าอยู่
    • Declarative Templating API ระดับสูงกว่าจะลดภาระการสร้างเฟรมเวิร์ก และช่วยตรวจสอบ/เติมเต็มข้อเสนอ API ระดับต่ำได้

จุดร่วมของไวยากรณ์และ semantics

  • ระบบเทมเพลตฝั่ง client ที่ได้รับความนิยมส่วนใหญ่มีโครงสร้างร่วมกันคือผสาน มาร์กอัปกับ bindings
    • ตัวคั่น expressions, control flow และตัวระบุชนิด binding ต่างกันเล็กน้อย แต่มีจุดร่วมมากกว่า
    • แม้ระหว่าง Vue, Angular, Svelte ที่ใช้ HTML กับ React, Lit, Solid ที่ใช้ JavaScript ก็มีความคล้ายกัน
  • ใน API ที่ใช้ JavaScript เทมเพลตมักเป็น expression และการ compose ทำผ่านการซ้อนหรืออ้างอิง template expressions ส่วน control flow ให้ JavaScript จัดการ
  • ระบบจำนวนมากที่ใช้ JavaScript API จะคืนคำอธิบาย DOM จาก template expression แล้วนำไปใช้ด้วยการเรียกฟังก์ชัน render แยกต่างหาก
    • ส่วนใหญ่จะอัปเดต DOM ด้วยการเรียก render เดิม
    • บางระบบเลี่ยงวิธีนี้ด้วย reactivity แบบละเอียด
  • E4X และ E4H เพิ่มไวยากรณ์ใหม่เพื่อใส่มาร์กอัปลงใน JavaScript เหมือน JSX แต่คืนค่าชิ้นส่วน DOM เอง ไม่ใช่คำอธิบาย DOM
    • เหมาะกับการสร้าง DOM เริ่มต้น แต่การอัปเดตยังคงเป็น imperative

API ที่แสดงได้ด้วย JavaScript ในวันนี้

  • JavaScript มี tagged template literals สำหรับ embedded DSL แบบ HTML อยู่แล้ว
  • สามารถแสดงเทมเพลตใน DOM API ได้โดยไม่ต้องเพิ่มไวยากรณ์ JavaScript ใหม่
  • ไลบรารียอดนิยมแสดงให้เห็นแล้วว่าแนวทางนี้ทำงานได้ดี
  • การเดินหน้าข้อเสนอโดยไม่ต้องมีไวยากรณ์ใหม่เป็นเรื่องสำคัญต่อความเป็นจริงในการทำให้เป็นมาตรฐาน

ความสัมพันธ์ระหว่าง JSX กับ native template API

  • tagged template literals เป็นฟีเจอร์ทรงพลังของ ES2015 แต่ในระบบคอมโพเนนต์ฝั่งผู้ใช้ มี overhead ทางไวยากรณ์มากกว่า JSX
  • JSX ได้รับความนิยมสูง แต่ มีแค่ไวยากรณ์ ไม่มี runtime semantics
    • หากจะทำให้เป็นมาตรฐาน ต้องกำหนด semantics ไม่ใช่แค่เพิ่มไวยากรณ์ใหม่
    • วิธีมองเป็นการเรียก createElement() ที่นิยามไว้รอบๆ ถูกตัดออกไป
    • วิธีสร้าง object tree อาจผสมส่วนสแตติกกับส่วนไดนามิกจนขัดขวางแพตเทิร์นการอัปเดตที่มีประสิทธิภาพกว่า
  • หากข้อเสนอ Records and Tuples เดินหน้าอยู่ JSX ก็อาจสร้าง Records ที่มี boxes ได้ แต่ข้อเสนอนั้นหยุดชะงัก โดยเฉพาะในส่วน record identity และ box
  • เพื่อพิสูจน์ว่าไวยากรณ์และ semantics แบบ JSX เหมาะกับ DOM templates เต็มรูปแบบหรือไม่ จำเป็นต้องมีระบบเทมเพลตเป้าหมาย
    • เทมเพลตของ React ไม่มีวิธี bind อย่างชัดเจนกับ properties และ events ของ DOM elements หรือใช้ directives กับ elements
  • JSX แบบไม่เป็นมาตรฐานในปัจจุบันเป็นไวยากรณ์ล้วนๆ ที่ไม่มี runtime semantics ดังนั้นจึงสร้างคอมไพเลอร์ที่แปลง JSX เป็น tagged template literal ได้
    • มีกรณีอย่าง JSX-to-Lit อยู่แล้ว
    • native template API อาจเป็น เป้าหมายการคอมไพล์ ที่ให้นักพัฒนาเลือกไวยากรณ์ตามต้องการได้

เหตุผลที่ควรมอง JavaScript API ก่อนเทมเพลตที่ใช้ HTML

  • นักพัฒนาเว็บจำนวนมากต้องการระบบเทมเพลตที่ใช้ HTML แบบครบฟีเจอร์
    • มีความต้องการจากชุมชนผู้ใช้ Web Components, ผู้ใช้เฟรมเวิร์ก และนักพัฒนา vanilla
    • นักพัฒนาบางคนเคยคาดหวังว่า <template> element, declarative shadow DOM และ Web Components จะให้ความสามารถแบบนี้
  • เทมเพลตที่ใช้ HTML เป็นงานใหญ่กว่า API ที่ใช้ JavaScript มาก
    • ไวยากรณ์ binding
    • ภาษา expression
    • ไวยากรณ์ control flow
    • กลไกการอัปเดตเทมเพลต
  • ยังไม่มีวิธีโหลดนิยามเทมเพลตที่ใช้ HTML แบบ native
    • HTML Imports ของ Web Components v0 หายไปแล้ว และ HTML Modules ก็ยังไม่มี
    • หากต้องใส่ HTML templates ไว้ใน JavaScript modules อยู่แล้ว การใช้ JavaScript expressions ใน lexical scope เดียวกับข้อมูลจะดีกว่า
  • Polymer 3 ย้าย HTML templates ของ Polymer 2 มาเป็น JavaScript และสิ่งนี้นำไปสู่ Lit โดยตรง
    • การให้ JavaScript ทำงานที่เหมือนสคริปต์ทำให้โค้ดน้อยลงและประสบการณ์ดีขึ้น
  • JavaScript API อาจเป็นทั้ง subset และฐานตั้งต้นของ API ที่ใช้ HTML
    • เมื่อ JavaScript API เข้ามาและผ่านการพิสูจน์แล้ว งานของ HTML API จะเหลือการนิยาม bindings, expressions, control flow และ module system

ตัวเลือกของโมเดล reactivity

  • ข้อเสนอ DOM template ช่วงแรกไม่ได้รวมการอัปเดต แต่ระบบใน userland ได้สำรวจโมเดล reactivity และแนวทาง implementation มาเพียงพอแล้ว
  • แนวทาง reactivity หลักๆ แบ่งได้เป็นสามแบบ
    • VDOM และ diffing ของ React
    • template identity ของ Lit
    • Signals และ reactivity แบบละเอียดที่ใช้ใน Solid, Svelte, Vue, Angular และอื่นๆ
  • diffing เข้าใจง่ายและใช้ได้กับข้อมูลทุกแบบ แต่ช้ากว่าแนวทางอื่น
    • ความแตกต่างของ diffing algorithms อาจสังเกตได้
    • การทำ diffing algorithm เดียวให้เป็นมาตรฐานและให้วิศวกรแพลตฟอร์มยอมรับ overhead เป็นเรื่องยาก
  • template identity คือวิธีที่อัปเดตหาก DOM ปัจจุบันถูกเรนเดอร์จากเทมเพลตนั้น มิฉะนั้นก็แทนที่
    • เร็ว และให้ผลลัพธ์คล้าย diffing มากใน use cases จำนวนมาก
    • เข้ากันได้ดีกับ tagged template literals, การแปลง JSX และเทมเพลตที่ใช้ HTML
    • semantics เรียบง่าย จึงระบุในสเปกได้ง่าย
  • Signals เป็นโมเดลที่ควรรวมไว้ใน reactive DOM API และ template API ใหม่
    • มี ข้อเสนอ JavaScript Signals แต่ยังไม่ใช่ฟีเจอร์ native ของแพลตฟอร์ม และไม่รับประกันว่าจะถูกนำมาใช้
    • ระบบที่ใช้ Signals ทำงานดีที่สุดเมื่อห่อข้อมูลทั้งหมดเป็น signal
    • เนื่องจากมีข้อมูลที่ไม่ใช่ signal และ platform APIs จำนวนมากที่ไม่สร้าง signal การเรนเดอร์ซ้ำจึงเป็นวิธีง่ายๆ ในการสะท้อนการเปลี่ยนแปลงเหล่านั้น
  • template identity และ Signals อยู่ร่วมกันได้
    • เทมเพลตที่ส่งเฉพาะ signal ให้ bindings สามารถอัปเดตด้วย signal ได้โดยไม่ต้องเรนเดอร์ซ้ำ
    • เทมเพลตที่อ้างอิงข้อมูลที่ไม่ใช่ signal จำเป็นต้องเรนเดอร์ซ้ำ
    • โดยปกติการเรนเดอร์ซ้ำจะทำโดยอัตโนมัติในชั้นคอมโพเนนต์หรือเฟรมเวิร์ก เช่น reactive component properties

การอภิปรายมาตรฐานและงานที่เหลือ

  • การอภิปรายเรื่อง native declarative JavaScript template API เริ่มขึ้นที่ WICG webcomponents#1069
  • API นี้อาจเป็นขั้นต่อไปที่สมเหตุสมผลของ DOM creation API
    • เป็น primitive สำหรับสร้าง DOM ที่เขียนง่ายและปลอดภัยสำหรับนักพัฒนาเว็บแบบ vanilla
    • มีประโยชน์ทันทีต่อไลบรารี Web Components ที่มีอยู่ เช่น Lit, FAST และ HyperElement
    • มีประโยชน์ต่อผู้ใช้ raw Web Components API และเป็นฐานตั้งต้นสู่ API สำหรับนิยาม reactive components ที่ครบถ้วนกว่า
    • เฟรมเวิร์กใหม่สามารถสร้างบน API นี้ได้
    • เฟรมเวิร์กเดิมสามารถใช้เป็น compile target, runtime backend หรือเป้าหมายที่รองรับโดยตรงได้
    • มีประโยชน์ทั้งกับเทคนิคการเรนเดอร์ซ้ำและ Signals
    • เป็นฐานตั้งต้นสู่ declarative HTML templates และ declarative custom elements
    • พื้นผิว API ที่ต้องตกลงและระบุในสเปกค่อนข้างเล็ก
    • ช่วยนิยาม semantics ของเทมเพลต
  • งานนี้เชื่อมโยงกับการทำข้อเสนอ DOM Parts ให้สมบูรณ์
    • ยังช่วยนิยาม DOM Parts และพิสูจน์ประโยชน์ของมันด้วย
  • แม้พื้นผิว API และไวยากรณ์จะไม่ใหญ่มาก แต่พื้นที่พฤติกรรมและ DOM Parts API ระดับล่างมีขนาดใหญ่
  • reactivity แบบละเอียดต้องการ DOM scheduler ในรูปแบบใดรูปแบบหนึ่งด้วย
  • ยังมีหลายสิ่งที่ต้องตัดสินใจ ต้องหาฉันทามติ ต้องระบุในสเปก และต้องทดสอบ จึงจำเป็นต้องร่วมมือกัน
  • นักพัฒนาที่สนใจสามารถคอมเมนต์ที่ webcomponents#1069 หรือติดต่อทาง Bluesky

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

 
GN⁺ 2025-06-28
ความคิดเห็นจาก Hacker News
  • คำพูดที่ว่า “เรารู้ว่าไวยากรณ์แบบไหนเหมาะกับเทมเพลต” ฟังดูน่าขำมาก เพราะจริง ๆ แล้วผมคิดว่าเรายังไม่รู้อะไรเลยด้วยซ้ำ เทมเพลตที่ดีไม่น่าใช่ ไวยากรณ์เชิงสัญลักษณ์ แต่เกือบจะแน่นอนว่าน่าจะใกล้เคียงกับ เครื่องมือแบบภาพ มากกว่า ซึ่งนั่นก็เป็นเหตุผลว่าทำไมเครื่องมือเก่า ๆ อย่าง Dreamweaver ถึงเคยประสบความสำเร็จ และทำไมนักออกแบบถึงเรียนรู้ผ่านเครื่องมืออย่าง Photoshop
    อีกอย่างก็น่าเสียดายที่มันดูเหมือนความพยายามจะสร้าง XSLT ขึ้นมาใหม่ สุดท้ายแล้วก็ต้องมีคนที่อยากทำสิ่งที่สามารถทำเทมเพลตจากชิ้นส่วนที่ไม่ well-formed ได้ แต่พอเอามารวมกันแล้วจะกลายเป็นสิ่งที่ well-formed เช่นเดิม รวมถึงเอนทิตีที่เชื่อมโยงกันอยู่ภายในหน้าเดียวกัน แต่ไม่ได้อยู่ใน tree เดียวกันด้วย ตัวอย่างง่าย ๆ ก็คือ label กับ for ในมาร์กอัปทั่วไป
    ถ้าเป็นไปได้ ผมก็อยากให้มีความพยายามน้อยลงในการฝืนยัดทุกเทมเพลตให้เข้ากับเครื่องจักร Rube Goldberg ที่เรียกว่าเลย์เอาต์เอกสารมาตรฐานของมาร์กอัป ผู้คนชอบเดินอ้อมไปทางที่ซับซ้อนเกินเหตุเพื่อจำลองสิ่งที่จริง ๆ แล้วทำได้ค่อนข้างดีด้วยการใช้ absolute positioning อย่างระมัดระวัง แน่นอนว่าการจัดให้ตรงกันอาจต้องมีการคำนวณ แต่ผมไม่เข้าใจว่าทำไมเราต้องบังคับให้เครื่องคำนวณสิ่งเดิมซ้ำแล้วซ้ำอีกสำหรับข้อมูลชุดเดียวกันด้วย

    • ผมไม่เคยชอบ XML แต่ XSLT เป็นฟีเจอร์เด็ดที่สามารถกอบกู้ ecosystem นั้นได้ และผมก็ยังคิดแบบนั้นจนถึงตอนนี้ มันยังรองรับอย่างกว้างขวางในเบราว์เซอร์อยู่เลย
      XML เคยฮิตในที่ที่ไม่เหมาะ เช่น การตั้งค่า หรือการสื่อสารระหว่างโปรเซส แต่กลับซบเซาลงในพื้นที่ที่มันน่าจะเปล่งประกายได้จริงในฐานะภาษามาร์กอัปที่มีความสามารถด้านการแปลงข้อมูลอันยอดเยี่ยมอย่าง XSLT ซึ่งก็น่าเสียดาย
      จุดที่ XSLT พังคือมันเป็น DSL ของจริง แถมยังเป็น DSL แบบประกาศล้วน บริสุทธิ์ และเชิงฟังก์ชันด้วย ผู้คนชอบยกย่อง DSL กันในทางคำพูด แต่ในทางปฏิบัติมันมักกลายเป็นแค่การเล่นไวยากรณ์ที่ไม่สามารถยกระดับ abstraction เหนือความหมายเชิงกระบวนวิธีของภาษาโฮสต์ยอดนิยมได้ พอเจอ DSL ที่ออกแบบมาดีและทำให้เรื่องยากกลายเป็นเรื่องเล็กน้อย คนกลับไม่ยอมเรียนรู้มัน
    • ผมไม่รู้ว่าคุณไปสรุปแบบนั้นได้อย่างไร สิ่งที่คุณพูดดูเหมือนจะเป็น ความไม่พอใจต่อ HTML+CSS โดยรวม มากกว่าจะเป็นเรื่องวิธีสร้างเทมเพลต
      และผมก็สงสัยเหมือนกันว่าทำไมถึงพูดถึง absolute positioning เพราะผมเห็นการพูดแบบนี้ซ้ำ ๆ บน HN แน่นอนว่า absolute positioning มีที่ทางของมัน และหลายกรณีก็จำเป็น
      แต่ถ้าเอาไปใช้กับเลย์เอาต์ของหน้าเว็บหรือแอป จากประสบการณ์ของผม ส่วนใหญ่มันคือฝันร้ายที่พังทันทีเมื่อเนื้อหาหรือขนาดหน้าจอเปลี่ยนไปเพียงเล็กน้อย แม้แต่เลย์เอาต์หนังสือพิมพ์ฉบับพิมพ์เองก็ยังทำแบบนั้นไม่ได้ เพราะมีเรื่อง typography เข้ามาเกี่ยวข้อง
      ตอนที่ผมทำงานกับ CSS หนัก ๆ ถ้าต้องไปรับช่วงต่อเลย์เอาต์ที่มีคนทำแบบ “เกือบเสร็จแล้ว” ด้วย absolute positioning การแก้ให้ถูกต้องจะกินเวลามหาศาล และการทำใหม่ด้วย flex หรือ normal flow จะเร็วกว่าเสมอ เพราะเมื่อใช้ absolute positioning เป็นเครื่องมือหลักในการจัดเลย์เอาต์ ปัญหามักอยู่ในระดับที่แทบแก้ไม่ได้จริง
      อาจจะมีเทคนิคที่สมเหตุสมผลโดยใช้ calc() กับ viewport unit แต่จากประสบการณ์ของผม ถ้าไม่ได้เป็นคอนเทนต์และขนาด viewport ที่คงที่แบบสมบูรณ์ absolute positioning ก็ไม่เหมาะกับงานเลย์เอาต์
    • บนเว็บมีข้อกำหนดว่าเอกสารต้องดูดีบนทุกขนาดอุปกรณ์ ทุกสัดส่วน ทุกแนวการวาง และทุกความสามารถของอุปกรณ์ แอปทั่วไป เช่น แอปบน Windows ไม่มีข้อกำหนดแบบนี้ และแอปมือถือก็มีขนาดมาตรฐานอยู่ไม่กี่แบบ มีแค่เว็บเท่านั้น ที่ต้องเจอทั้งสองอย่างพร้อมกัน
    • ผมคิดว่าระหว่าง React กับ Svelte มีแค่ความคล้ายกันภายนอกเท่านั้น ทั้งคู่ใช้ไวยากรณ์ที่อิงกับ HTML อย่างมาก แต่กลไกการทำงานต่างกันมาก
      React เป็นเฟรมเวิร์กหลักเพียงตัวเดียวที่โดยมากทำงานในลักษณะที่ฟังก์ชัน JavaScript ทั่วไปคืนค่าการแทนมาร์กอัปแบบหน่วงเวลาในรูป JSX กลับมา React ไม่มีแนวคิดเรื่องการวนซ้ำหรือการเรนเดอร์ตามเงื่อนไขในระดับเทมเพลต สิ่งเหล่านั้นจัดการด้วย JavaScript ปกติ
    • การหัวเราะเยาะต่อหน้าคนที่พยายามผลักดันความก้าวหน้าของเว็บแพลตฟอร์มไม่ใช่ท่าทีที่ดีนัก เพราะความก้าวหน้านั้นเป็นประโยชน์กับทุกคน
      และตอนนี้ผมคิดว่าเรารู้แล้วว่าไวยากรณ์เทมเพลตที่ดีควรเป็นอย่างไร โดยพื้นฐานแล้วก็คือ JSX ต่อให้ผมไม่ได้ชอบ React มากนักก็ยังพูดแบบนั้นได้ JSX กวาดไปทั่วทั้งเว็บ ถูกดัดแปลงให้เข้ากับหลายเฟรมเวิร์ก และยากจะปฏิเสธว่า JavaScript template system ต่าง ๆ ก็กำลังลู่เข้าสู่คุณสมบัติร่วมกัน คือปฏิบัติต่อเทมเพลตเหมือน expression ประกอบซ้อนกันได้ และใช้ JavaScript เองจัดการ control flow แทนที่จะมีไวยากรณ์เทมเพลตเฉพาะของตัวเอง
  • บทเรียนพื้นฐานที่ได้เรียนซ้ำแล้วซ้ำเล่าคือ API/ABI ไม่ใช่สภาวะสุดท้าย ความต้องการของแอปพลิเคชันไม่ได้ถูกตอบโจทย์อย่างถาวรด้วย API ที่เสถียรเพียงตัวเดียว และก็ไม่อาจผลักปัญหาในอนาคตทั้งหมดให้กลายเป็นปัญหาระดับแอปได้
    ข้อเสนอนี้แสดงให้เห็นได้ดีว่าปัญหาทั่วไปของแพลตฟอร์มมักถูกแก้ในชั้นบนอย่าง React ก่อน แล้วเมื่อท้ายที่สุดถูกยอมรับว่าเป็นปัญหาจริง ก็จะถูกดันลงมาข้างล่าง โพลีฟิลก็เป็นตัวอย่างแบบเดียวกัน
    เมื่อข้อเสนอแบบนี้สำเร็จ มันอาจได้รับความสนใจอยู่พักหนึ่ง แต่ช่วงชีวิตที่มีประโยชน์ส่วนใหญ่กลับกลายเป็นของเก่าที่ผู้คนพยายามหาทางเลี่ยง ไม่ว่าจะเป็น DOM API, ECMA เวอร์ชันต่าง ๆ, เบราว์เซอร์เก่า ๆ และเทคโนโลยีมีประโยชน์ทุกอย่างที่แก้ไม่ได้เพราะเป็นส่วนหนึ่งของระบบ
    เราจะคิดโดยวาง เอนโทรปี, การขยายตัว, ความเข้ากันได้ย้อนหลัง เป็นกรณีใช้งานหลักได้ไหม

    • ทุกฟีเจอร์ของมาตรฐานเว็บคือโค้ดเพิ่มที่ต้องบำรุงรักษาอย่างระมัดระวัง และยังเป็นโค้ดเพิ่มที่ใครก็ตามที่อยากสร้างเบราว์เซอร์ที่สอดคล้องตามมาตรฐานต้องลงมือทำด้วย ผมอยากให้โครงการอย่าง https://servo.org/ มีโอกาสไล่ตามทันเมื่อเวลาผ่านไป มากกว่าจะต้องคอยวิ่งไล่ขอบเขตที่ขยายขึ้นเรื่อย ๆ
      ผมอยากให้เว็บแพลตฟอร์มมีความสามารถทุกอย่างที่เนทีฟแพลตฟอร์มมีได้ แน่นอนว่าต้องอยู่ภายใต้ข้อจำกัดด้านความเป็นส่วนตัวและ sandboxing และผมก็อยากให้ประสบการณ์นักพัฒนาของเว็บดีเยี่ยมด้วย
      แต่สิ่งนี้ต้องสมดุลกับผลลัพธ์ของความซับซ้อนที่เพิ่มขึ้น ในกรณีนี้ผมยังไม่มั่นใจว่า native template ช่วยให้ประสบการณ์นักพัฒนาดีขึ้นจริงหรือไม่ และดูไม่ออกว่าประโยชน์จะมากกว่าต้นทุน
    • getElementById ก็น่าจะเสถียรมาราว 25 ปีแล้วไม่ใช่หรือ คำพูดที่ว่า “ไม่มีอะไรอย่าง API ที่เสถียร” เป็นคำพูดของคนที่ไม่มีความสามารถหรือไม่มีความตั้งใจจะสร้างอินเทอร์เฟซที่อยู่ได้ยาวนาน มันไม่ใช่กฎของจักรวาล แต่ใกล้เคียงกับความยอมแพ้ส่วนตัวมากกว่า ตัวอย่างโต้แย้งมีเยอะมาก
      ความต้องการของแอปพลิเคชันนั้นไร้ขอบเขตเหมือนความต้องการอื่น ๆ และมันควรถูกตอบสนองด้วยการ เพิ่ม API ใหม่ ไม่ใช่ด้วยการทำลาย API ที่ใช้งานได้ดีอยู่แล้ว
    • บนเว็บนั้น API/ABI คือสภาวะสุดท้ายจริง ๆ เมื่อเปิดสู่เว็บแล้ว ก็จะมีใครสักคนพึ่งพารูปแบบนั้นอย่างเป๊ะไปตลอดกาล
      จึงยังมี API ที่ต้องไปพัวพันกับเรื่องอย่าง smooshgate เพราะการตัดสินใจเมื่อ 20 ปีก่อน: https://developer.chrome.com/blog/smooshgate
    • ระหว่างทาง ความสามารถพื้นฐานก็ยกระดับขึ้นอีกขั้น และการที่ความต้องการฝั่งผู้ใช้จะคอยหาช่องว่าง กรณีใช้งาน และจุดบอดใหม่ ๆ เจออยู่เสมอ ไม่ได้แปลว่า การอัปเดตแบบค่อยเป็นค่อยไป ไม่มีค่า
    • นั่นจึงเป็นเหตุผลที่เรามีเวอร์ชัน และคงความเข้ากันได้ย้อนหลังกับเวอร์ชันเก่า โดยไม่ไปเปลี่ยนอินเทอร์เฟซที่ “เก่า” ไม่ใช่หรือ
  • เว็บต้องการ native template, reactivity และ data binding จริง ๆ ลองนึกดูว่ามี CPU และแบนด์วิดท์ถูกเปลืองไปมากแค่ไหนกับการที่ผู้ใช้หลายพันล้านคนต้องดาวน์โหลด พาร์ส และรันสิ่งอย่าง React

    • ตอนนี้มี LLM กับคริปโตแล้ว เลยทำให้ความสิ้นเปลืองแบบนั้นดูเล็กน้อยไปเลย
    • ข้อเสนอ Signals ของ TC39 กำลังทำให้บางส่วนของเรื่องนี้คืบหน้า
    • ถ้ามี data binding แบบสองทางกับ JSX ที่ทำซ้ำได้ประมาณหนึ่ง จริง ๆ ก็น่าจะพอสำหรับคนส่วนใหญ่แล้ว
    • React ไม่น่าจะเรียกว่าเป็น template ได้ไม่ใช่หรือ
  • ส่วนของ Signals บอกอะไรหลายอย่าง และแสดงให้เห็นได้ดีว่าไอเดียนั้นยอดเยี่ยม แต่ในทางปฏิบัติกลับยาก
    ผมเข้าใจว่าทำไมผู้เขียนถึงชอบ Signals ทุกโปรเจกต์ที่ใหญ่พอก็มักมีต้นไม้คำนวณแบบ DAG ที่ทำไว้ครึ่ง ๆ กลาง ๆ และการที่ภาษาหนึ่งจะทำให้มันเป็นมาตรฐานก็สมเหตุสมผล
    แต่ abstraction แบบนี้มี ต้นทุนด้านการรับรู้และต้นทุนด้านการนำไปใช้ สูง
    เหมือนงานวิศวกรรมส่วนใหญ่ ปัญหาคือการแลกเปลี่ยนกัน โมเดลของ React ช้าเพราะอัปเดต global state แล้วเรนเดอร์ใหม่ทั้งหมด แต่เข้าใจง่ายในหัว ส่วนโมเดล Signals เร็ว แต่ต้องใช้ความพยายามมากเกินไป
    แอปส่วนใหญ่ไม่จำเป็นต้องเร็วระดับสุดโต่ง และผู้คนก็น่าจะเลือก React ที่เรียบง่ายกว่า
    แต่ Signals ก็แทบไม่เกี่ยวกับ template อยู่แล้วไม่ใช่หรือ ถ้าอย่างนั้นทำไมต้องเลือกอย่างใดอย่างหนึ่ง และเราจะมี template กับ Signals แยกจากกันไม่ได้หรือ
    พอคิดเรื่อง template ก็จะต้องเจอคำถามว่าจะแทรก template node ลงใน DOM ตรงไหน และต้องมีวิธีบอกมันอย่างไรให้รู้ว่าต้องอัปเดตเมื่อเกิดการเปลี่ยนแปลง ตรงนี้แหละที่ข้อเสนอแบบนี้มักล้มเหลว
    API ตรงนี้ต้องเลือกข้างสักทาง ในทางเทคนิคอาจเปิดให้มีได้ทั้งสองแบบ แต่จะน่ากลัวมาก และนักพัฒนาก็คงไม่มีวันเห็นพ้องกันได้ว่าแบบไหนควรเป็นคำตอบ
    ปัญหาใหญ่ของ UI ไม่เคยอยู่ที่นิยามอย่างไร แต่อยู่ที่ อัปเดตอย่างไร เสมอมา Microsoft เคยพยายามนิยามโมเดลมากมายอย่าง MVC, MVP, MVVM และก็ล้มเหลว ทั้งหมดล้วนเจ็บปวด จากนั้น imgui ก็พูดว่า “ถ้า UI ไม่มี state เลยล่ะ?” ซึ่งก็ค่อนข้างดี แต่หนักกับ CPU มาก
    บางทีหนึ่งในเหตุผลสำคัญที่สุดที่เว็บแอปประสบความสำเร็จ อาจเป็นเพราะ DOM ไม่ได้บังคับวิธีผูกข้อมูลเข้ากับวิว และอาจเป็นเพราะอย่างนั้นเองที่เราหนีจากนรกของเฟรมเวิร์กได้ยาก

    • ตอนนี้มีหลายเฟรมเวิร์กที่ทำ fine-grained diffing ได้ดี โดยไม่ต้องพึ่ง Signals หรือ proxy หรือ reactive primitive แบบอื่น ๆ มันยังเป็นโมเดล React แบบไหลจากบนลงล่างโดยพื้นฐาน แต่เร็วกว่าเยอะ และไม่มีแนวคิดประหลาดอย่าง hooks หรือ dependency array ที่ต้องจัดการเองและสิ้นเปลือง
      ส่วนตัวผมชอบ ivi-js: https://github.com/localvoid/ivi
      มันช้ากว่า vanilla JavaScript ที่เร็วที่สุด อัปลักษณ์ที่สุด เชิงคำสั่งที่สุด และบำรุงรักษาไม่ได้ที่สุด ซึ่งสุดท้ายแล้วคุณจะไปถึงได้ถ้าคิดแต่จะชนะ benchmark อยู่เพียง 8% เท่านั้น
      https://krausest.github.io/js-framework-benchmark/2025/table...
    • แม้ Microsoft จะใช้โมเดลเหล่านั้นในหลายช่วงเวลา แต่สิ่งที่นิยามขึ้นเองจริง ๆ มีแค่ MVVM เท่านั้น MVC มาจาก Xerox PARC และ MVP มาจาก Taligent
    • ในฐานะนักพัฒนา ผมก็ยินดีเลือกสิ่งที่ทำให้นักพัฒนาต้องคิดหนักขึ้นอีกนิด ถ้ามันทำให้ฮาร์ดแวร์ แบนด์วิดท์ และโลกเบาขึ้น
      ผมอยากให้คนยอมรับมากขึ้นว่า แทนที่จะบอกว่าแอปส่วนใหญ่ไม่ต้องเร็วระดับสุดโต่ง แอปนั้น ควรมีขนาดเบา
      ผมเห็นด้วยว่าคนเลือก React เพราะมันเรียบง่ายกว่า แต่นั่นก็เป็นเหตุผลเดียวกันกับที่ผมไม่ชอบ React
  • แทนที่จะรับ JSX มาใช้ อยากให้ Kotlin เข้าใกล้แนวทางที่ให้ไวยากรณ์ทั่วไปสำหรับ DSL ด้วย receiver และ builder มากกว่า และไวยากรณ์นั้นก็เหมาะกับการแสดงลำดับชั้นของคอมโพเนนต์ด้วย
    มันน่าจะมีประโยชน์อย่างกว้างขวาง ไม่ใช่แค่กับ HTML template แต่ยังใช้แสดงการตั้งค่าและโครงสร้างได้หลายประเภท
    ส่วนความหมายเชิงอรรถศาสตร์ที่แท้จริงของ template และ data binding ก็สามารถปล่อยให้เป็นชุดฟังก์ชันมาตรฐานที่ใช้ความสามารถทางไวยากรณ์แบบนั้นได้ เหมือนที่เห็นใน Jetpack Compose

    • ไม่ต้องมีอะไรมากด้วยซ้ำ แค่การวนซ้ำ เงื่อนไขสำหรับแอตทริบิวต์ และเงื่อนไขสำหรับโหนดก็พอ จริง ๆ แล้วระดับนั้นทำได้แม้กระทั่งด้วย ความสามารถร่วมกันข้ามภาษา
  • สิ่งสำคัญอีกอย่างคือบทความนี้เขียนโดยหนึ่งในคนที่มีประสบการณ์มากที่สุดในสายนี้ เขาเป็นผู้เขียนหลักของ Lit / Polymer และเป็นคนที่ทำงานด้าน Web Components ที่ Google พร้อมทั้งมีส่วนร่วมกับสเปก DOM หลัก ๆ ที่กลายเป็นส่วนหนึ่งของเว็บแพลตฟอร์ม

    • กลับกัน ผมมองว่าเขาเป็นหนึ่งในคนที่สร้างปัญหามากกว่าที่แก้ ด้วยการผลักดันสเปกที่ยังไม่สุกงอมแบบหุนหันพลันแล่น เขาผลัก “ทางแก้” ที่ต้องการ สเปกเว็บใหม่มากกว่า 20 รายการ เพียงเพื่อไล่ตามสิ่งที่อยู่ใน userland ทำกันอยู่แล้ว และยังเมินหรือ gaslight คนที่ไม่เห็นด้วย 100%
      Safari ยืนกรานมาตั้งแต่ 15 ปีก่อนแล้วว่าตรงนี้ควรมีแนวทางเชิงประกาศ
  • มีใครอีกไหมที่รู้สึกว่า declarative template แย่กว่า jQuery เสียอีก ผมใช้ React มาเกือบ 10 ปี แต่ยิ่ง SPA ซับซ้อนขึ้น ก็ยิ่งอยาก ควบคุม DOM แบบ imperative โดยตรง
    เหตุผลคือ DOM เป็น abstraction ที่รั่ว และในบางระดับก็รู้สึกว่าวิธีที่ให้การเขียนครั้งสุดท้ายเป็นฝ่ายชนะนั้นดีกว่า
    ผมเข้าใจว่า declarative template พยายามจัดการเรื่องนี้ แต่พอเริ่มแชร์ state ที่เปลี่ยนแปลงได้ระหว่างคอมโพเนนต์ วิธีนี้ก็พังเร็วมาก

    • ฝั่ง React มีแนวโน้มจะมองว่าการเรียก DOM API โดยตรงเป็นบาปใหญ่โต บางครั้งแค่ถือ ref ไว้ แล้วถ้าจะพูดกันตรง ๆ จะหา component ด้วย id แล้วจัดการตรง ๆ เลยก็ได้ จริง ๆ แล้วไลบรารีที่ “เร็ว” และ rerender น้อย เช่นไลบรารีฟอร์ม ก็ทำแบบนั้น
    • ผมไม่ได้ชอบ React แต่ก็ไม่เห็นด้วยกับความรู้สึกนี้ อย่างแรกคือคุณออกจาก declarative DOM ไปใช้ innerHTML กับ ref ได้เต็มที่อยู่แล้ว
      อย่างที่สอง ผมนึกไม่ออกว่ามีอะไรที่ควบคุม DOM แบบ imperative แล้วจะยุ่งยากน้อยกว่าแบบ declarative ได้ นอกจากเมธอดเฉพาะอย่าง attachShadow(), showModal() แต่ถึงอย่างนั้น ถ้าห่อด้วยคอมโพเนนต์ 10 บรรทัดก็ทำให้เป็น declarative ได้
    • เห็นด้วยเต็มที่ ผมยังไม่เคยเห็นตัวอย่างสักอันที่ทำให้เชื่อได้ว่าอะไรอย่าง React ดีกว่าการใช้ HTML แยกกับ jQuery แม้เพียงนิดเดียว
  • เท่าที่รู้ Ryan Carniato กับ Solid JS ยังอยู่ระหว่างสำรวจว่าสิ่งที่ทำได้ด้วย Signals มีอะไรบ้าง ผมยังไม่คิดว่าการสำรวจใน userland ของพื้นที่นี้จะจบลงสมบูรณ์แล้ว และอาจยังมี นวัตกรรมเพิ่มเติม ได้

    • นอกฟองสบู่เว็บดีเวลอปเมนต์ ก็ยังมีงานวิจัยน่าสนใจมากเกี่ยวกับปัญหา incremental computation และ self-adjusting computation ซึ่งแม้แต่ Signals เองก็ไม่ได้เป็นแกนที่น่าสนใจนัก
  • ผมชอบทิศทางนี้ แต่ก่อนหน้านั้นคิดว่าบราวเซอร์ควรมี low-level API เพิ่มอีกไม่กี่อย่างก่อน
    แทบเป็นไปไม่ได้เลยที่ทุกคนจะเห็นพ้องกับระบบ template มาตรฐานระบบเดียว สิ่งที่บราวเซอร์พอทำได้แทนคือให้ low-level API สำหรับ apply diff กับ DOM แบบ native ที่มีประสิทธิภาพ
    ถ้าบราวเซอร์มีอะไรแบบนี้ในตัวก็คงดีมาก
    element.applyDiff(DocumentFragment | string, { method: 'innerHTML' | 'outerHTML' })
    วิธีนี้สามารถ apply diff แบบรบกวนน้อย เช่นคงสถานะโฟกัสขององค์ประกอบ ค่าที่ผู้ใช้ป้อน และสถานะของตัวเล่นเสียง/วิดีโอไว้ พร้อมกับเปลี่ยนแอตทริบิวต์ได้ ไลบรารี JavaScript อย่าง Idiomorph ก็ทำสิ่งนี้ได้ แต่ ทางออกแบบ native น่าจะเร็วกว่าได้มาก

    • ในบทความมีลิงก์ไปยังข้อเสนอ DOM part ซึ่งอาจเป็น low-level API ที่มีประโยชน์ มันอาจไม่เข้ากับเฟรมเวิร์กสาย VDOM แต่สำหรับเฟรมเวิร์กอื่น ๆ อาจช่วยให้รูปแบบการทำงานง่ายขึ้นและเปิดช่องให้ปรับแต่งประสิทธิภาพได้มากขึ้น
      มันน่าจะมีประโยชน์กับโปรเจ็กต์ที่ไม่ใช้เฟรมเวิร์กด้วย และถ้าข้อเสนอ Signals ถูกนำมาใช้ด้วยก็จะยิ่งมีประโยชน์เป็นพิเศษ
  • ข้อเสนอ Records and Tuples ไม่ได้แค่หยุดนิ่ง แต่ถูกถอนออกไปแล้ว https://github.com/tc39/proposal-record-tuple/issues/394
    ตอนนี้ https://github.com/tc39/proposal-composites เข้ามาแทนที่