Compiler vs Runtime
นี่คือความแตกต่างทางสถาปัตยกรรมที่ใหญ่ที่สุดระหว่าง React และ Svelte และกำหนดทุกสิ่งที่เกี่ยวข้อง React เป็น runtime library — ส่งตัวเองไปยัง browser และ reconcile virtual DOM ทุกครั้งที่ state เปลี่ยน Svelte เป็น compiler — วิเคราะห์ component ของคุณตอน build time และ output JavaScript ธรรมดาที่ update DOM โดยตรง เมื่อโค้ดถึง browser Svelte เองก็แทบจะหายไปแล้ว
สิ่งที่ React ส่งไปยัง browser
หัวข้อที่มีชื่อว่า “สิ่งที่ React ส่งไปยัง browser”React รวม reconciler, fiber scheduler, synthetic event system และ hooks runtime เข้าด้วยกัน — ทั้งหมดนี้ทำงานบน device ของผู้ใช้ทุกคน ทุกครั้งที่โหลดหน้า เมื่อ state เปลี่ยน React สร้าง virtual DOM tree ใหม่ diff กับ tree ก่อนหน้า แล้วจึง flush การเปลี่ยนแปลง DOM จริง ๆ ขั้นตอน diff นั้นเกิดขึ้นที่ runtime ใน browser
สิ่งที่ Svelte ส่งไปยัง browser
หัวข้อที่มีชื่อว่า “สิ่งที่ Svelte ส่งไปยัง browser”Svelte วิเคราะห์ template และ state ของ component ที่ build time และสร้างโค้ด DOM update แบบ imperative เป้าหมาย เมื่อ count เปลี่ยน compiled output จะเรียก textContent = count — DOM write โดยตรงหนึ่งครั้ง ไม่มี diffing ไม่มี reconciler “Runtime” ของ Svelte ที่ส่งมานั้นเล็กมาก (เป็นแค่ utility function จำนวนหนึ่งสำหรับสิ่งต่าง ๆ เช่น {#each} keyed list และ transition)
Mental model แบบ side-by-side
หัวข้อที่มีชื่อว่า “Mental model แบบ side-by-side”// React — ships reconciler + fiber + hooks runtime// On every setState:// 1. Re-run the function component// 2. Build a new virtual DOM tree// 3. Diff against the previous tree// 4. Flush real DOM changes
function Counter() { const [count, setCount] = React.useState(0); return ( <button onClick={() => setCount(c => c + 1)}> Count: {count} </button> );}<!-- Svelte — compiles to direct DOM code --><!-- On count change, compiler emits roughly: buttonText.data = "Count: " + count; No diffing. No reconciler. -->
<script> let count = $state(0);</script>
<button onclick={() => count++}> Count: {count}</button>ความหมายสำหรับคุณในฐานะ developer
หัวข้อที่มีชื่อว่า “ความหมายสำหรับคุณในฐานะ developer”Bundle size: bundle ของ React + ReactDOM มีขนาดอย่างน้อย ~42 kB (gzipped) ก่อนที่โค้ด app ของคุณจะเริ่ม Svelte แทบไม่เพิ่มอะไร — output คือโค้ด app ของคุณบวก runtime เล็ก ๆ ที่แชร์กัน
Performance: ไม่มีการ diff virtual DOM หมายความว่างานน้อยลงต่อการเปลี่ยนแปลง state ความแตกต่างนี้แทบไม่รู้สึกสำหรับ UI ส่วนใหญ่ แต่มีนัยสำคัญสำหรับ list ขนาดใหญ่ animation หรืออุปกรณ์ที่ช้า
Mental model: คุณเขียน declarative component เหมือนที่ทำใน React Compiler จัดการงาน imperative DOM ให้คุณ ไม่จำเป็นต้องคิดว่าทำงานอย่างไร — แค่รู้ว่า count++ จะ update ทุกที่ที่ count ปรากฏใน template โดยอัตโนมัติ
ไม่มี stale closure จาก diffing: เพราะ Svelte ไม่ re-run function component ทั้งหมดในแต่ละ update (ต่างจาก React ที่ re-render function component ใหม่) bug ประเภท stale closure ใน React hook จึงไม่มีในรูปแบบเดียวกันใน Svelte
ลองเล่น: ดู reactivity ในการทำงาน
หัวข้อที่มีชื่อว่า “ลองเล่น: ดู reactivity ในการทำงาน”$derived คือ equivalent ของ useMemo ใน Svelte — คำนวณใหม่โดยอัตโนมัติเมื่อ dependency เปลี่ยน ไม่ต้องใส่ dependency array เพราะ compiler ของ Svelte ติดตาม dependency ให้คุณเอง