ข้ามไปยังเนื้อหา

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 รวม reconciler, fiber scheduler, synthetic event system และ hooks runtime เข้าด้วยกัน — ทั้งหมดนี้ทำงานบน device ของผู้ใช้ทุกคน ทุกครั้งที่โหลดหน้า เมื่อ state เปลี่ยน React สร้าง virtual DOM tree ใหม่ diff กับ tree ก่อนหน้า แล้วจึง flush การเปลี่ยนแปลง DOM จริง ๆ ขั้นตอน diff นั้นเกิดขึ้นที่ runtime ใน 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)

React (runtime)
// 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 (compiled)
<!-- 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>

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

$derived คือ equivalent ของ useMemo ใน Svelte — คำนวณใหม่โดยอัตโนมัติเมื่อ dependency เปลี่ยน ไม่ต้องใส่ dependency array เพราะ compiler ของ Svelte ติดตาม dependency ให้คุณเอง

Svelte วิเคราะห์ component และสร้างโค้ด DOM update เมื่อใด?
React ใช้ virtual DOM เป็นหลักเพื่อ:
Equivalent ของ React useMemo ใน Svelte คืออะไร?
ข้อใดถูกต้องเกี่ยวกับ bundle size ของ Svelte?