Svelte

比較 Svelte 渲染元件的三個方法:mount vs render vs hydrate

Svelte Version: 5.25.7

Outline

  • render():在 Server 端上,將從 Component 產生 HTML。
  • mount():在 Client 端上,從空的 DOM 節點建立 Component 的 DOM 附加到 HTML。
  • hydrate():混合 render()mount()。功能上類似 mount(),但不是從空的 DOM 節點開始,而是從 Server 端 render() 過的資料開始建立。

Svelte Render VS Render VS Hydrate

使用時機

如果需要在 server 端渲染 e.g. SEO 的需求,可以使用 render(),Server 端會將完整的 HTML 輸出至 Client 端。而 mount() 完全相反,僅在 Client 端時建立 DOM 節點。而 hydrate() 同時兼顧了 Server 端 SEO 的需求與 Client 端與使用者互動的需求,

render:Server 端渲染

當您在 Server 端上使用 render() 功能時,Component 將被編譯為 HTML 字串,可以將其傳送到 Client 端:

1
2
3
4
5
6
7
8
9
10
11
// Server-side code (e.g., in a Node server)
import { render } from 'svelte/server';
import App from './App.svelte';

const result = render(App, {
props: { some: 'property' }
});

// Then send `result` as the response to the client.
result.body; // HTML <body> tag
result.head; // HTML <head> tag

App 為 Svelte 的 Componenet,props 則是傳入 App 的屬性參數。

mount:Client 端渲染

如果你有一個空 DOM 節點或是即沒有預先渲染的 HTML e.g. <div id="app"></div> 並且希望 Svelte 在 Client 端上從頭建立 DOM,可以使用 mount()

1
2
3
4
5
6
7
import { mount } from 'svelte';
import App from './App.svelte';

const app = mount(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});

hydrate:升級伺服器渲染的 HTML

假設以下程式碼已在 Server 端產生的 HTML 並傳送到 Client 端:

1
<div id="app">something</div>

我們可以在 Client 端上使用 hydrate() 來讓 Server 端渲染的物件具有互動性 (interactive)。

1
2
3
4
5
6
7
import { hydrate } from 'svelte';
import App from './App.svelte';

const app = hydrate(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});

可以想像成 Server 端已經渲染好 HTML,用 hydrate() 附加額外邏輯和事件處理來「提升」此靜態 HTML 的功能:

Reference

React vs Svelte 開發體驗:子元件暫時更新父層資料

當程式規模慢慢變大時,為了管理與維護會將大元件拆分成許多小元件,在父子元件之間傳遞資料是開發時很常見的。但在傳遞資料上,React 跟 Svelte 沒什麼區別,同樣都是將資料傳入元件的 attribute 中,子元件透過 props 來獲得父層傳入的資料。所以我們這章舉一個比較複雜一點的例子:讓子元件可以暫時更新資料,但如果父元件的資料更新時,子元件也要更新為父元件元件的值。我們將透過範例比較兩者在開發體驗上的差異。

開發體驗

開發者在使用工具、框架、語言、API、系統或流程時,整體的感受、效率、流暢度與滿意度。

使用情境

當你在開發表單、步驟流程或是可編輯區塊時,子元件常會需要「暫時修改」父元件提供的資料。例如使用者輸入值,但尚未儲存前,這些變更應該是本地的。這時候就需要讓子元件在不直接修改父層狀態的前提下,保有一定程度的控制權。

React:需要手動管理狀態同步

React 採用單向資料流設計,而且我們無法直接修改 props。在子元件想要暫時更新資料時,必須透過 useState 加上 useEffect 來同步 props 的變化 (demo)。

ParentComponent.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
const [count, setCount] = useState(0);

return (
<div>
<button onClick={() => setCount(count + 1)}>
clicks (parent): {count}
</button>
<ChildComponent count={count} />
</div>
);
}

export default ParentComponent;

ChildComponent.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { useState, useEffect } from 'react';

function ChildComponent({ count }) {
const [localCount, setLocalCount] = useState(count); // create a local count for temporary use

useEffect(() => {
setLocalCount(count);
}, [count]);

const increment = () => {
setLocalCount(localCount + 1);
};

return (
<button onClick={increment}>
clicks (child): {localCount}
</button>
);
}

export default ChildComponent;

在這個範例中:

  • 子元件透過 useState 創建一個本地的 localCount,用來「暫時更新」畫面上的計數值。
  • 當父元件的 count 改變時,useEffect 會同步更新 localCount
  • 子元件的操作不會影響父元件的實際資料。

Svelte:直覺操作、語法簡潔

Svelte 允許我們在子元件中直接修改 props,而不需要額外建立本地狀態。這種語法大幅簡化了開發流程,對開發者非常友善 (demo)。

Parent.svelte

1
2
3
4
5
6
7
8
9
10
11
<script>
import Child from './Child.svelte';

let count = 0;
</script>

<button onclick={() => (count += 1)}>
clicks (parent): {count}
</button>

<Child {count} />

Child.svelte

1
2
3
4
5
6
7
<script>
let { count } = $props();
</script>

<button onclick={() => (count += 1)}>
clicks (child): {count}
</button>
  • 無需 useEffect 或本地狀態。
  • 可直接操作傳入的 count,操作簡單明瞭。
  • 預設變更僅限於子元件本地,不會同步到父層(除非你明確綁定 bind: 或使用事件)。

以上 React 與 Svelte 兩個例子功能相同,但 Svelte 的語法設計,讓開發者可以更快速專注在邏輯本身,而非額外的狀態管理機制。

延伸閱讀

React vs Svelte 開發體驗:雙向資料綁定

資料綁定 (Data Binding) 是連結應用程式資料 (Application) 與使用者介面 (UI) 的方式或機制。React 是使用單向資料綁定 (one-way data flow),需手動呼叫 setState 來更新狀態;而 Svelte 使用 bind: 指令來達成雙向資料綁定。我們將透過範例來了解兩者在開發體驗上的差異。

開發體驗

開發者在使用工具、框架、語言、API、系統或流程時,整體的感受、效率、流暢度與滿意度。

使用情境

當你在開發表單、表單輸入與使用者互動或即時資料顯示,需要反向更新狀態變數,並即時顯示給使用者 (e.g. 動態價格計算、表單即時驗證、即時預覽)。

React:單向資料綁定

React 採用單向資料流 (one-way data flow),透過手動呼叫 setstate 來更新狀態。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { useState } from 'react';

function InputComponent() {
const [text, setText] = useState('');

return (
<>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<p>{text}</p>
</>
);
}
  • useState 宣告狀態變數 text,初始值為空字串。
  • value={text} 綁定輸入框顯示值。
  • onChange 在輸入變動時更新 text

Svelte:直覺式雙向綁定

Svelte 提供了 bind: 指令,簡化雙向資料綁定,讓變數與元件保持同步。

1
2
3
4
5
6
<script>
let text = '';
</script>

<input type="text" bind:value={text} />
<p>{text}</p>
  • 使用 let 宣告響應式 (reactivity) 變數 text
  • bind:value={text} 自動雙向綁定輸入值與變數。
  • 使用者輸入會更新 text,變數更新也會同步回輸入框。

哲學

React 與 Svelte 在資料綁定上的差異,反映了各自的框架哲學:

  • React 注重控制與可預測性,適合處理複雜應用邏輯與資料流。
  • Svelte 注重簡潔與開發效率,讓使用者開發時更貼近原生思維。

延伸閱讀

React vs Svelte 開發體驗:狀態管理

在管理資料狀態上,React 採用的是 useState Hook,而 Svelte 則是直接使用變數,使用起來更直觀。我們將透過範例來了解兩者在開發體驗上的差異。

開發體驗

開發者在使用工具、框架、語言、API、系統或流程時,整體的感受、效率、流暢度與滿意度。

React 狀態管理:使用 useState Hook

React 讓元件可以擁有內部狀態的方式是透過 useState Hook 來完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
import { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

return (
<button onClick={() => setCount(count + 1)}>
Counter:{count}
</button>
);
}

export default Counter;
  • useState(0):初始化 count 為 0。
  • setCount:更新 count 的函式,每次按鈕點擊讓值加 1。
  • 透過 React 的 Virtual DOM,變化的值會觸發元件重新渲染。

非同步更新注意事項

React 的狀態更新是非同步的,因此如果在同一函式中連續呼叫多次 setCount(count + 1),可能無法即時反映最新的狀態。建議改用以下方式來避免此問題:

1
setCount(prevCount => prevCount + 1);

這樣可以保證邏輯永遠是基於最新狀態更新。

Svelte 狀態管理:響應式變數

Svelte 採用一種更直覺的狀態處理方式。它不需要額外的 Hook,直接使用變數即可自動觸發畫面更新。

1
2
3
4
5
6
7
<script>
let count = 0;
</script>

<button on:click={() => count++}>
Counter:{count}
</button>
  • 使用 let count = 0 宣告變數。
  • 直接對 count 進行操作,例如 count++,Svelte 就能自動感知變化並更新 DOM。
  • 這是透過 Svelte 的 編譯時響應式系統 (reactivity system) 實現的,完全不需要 Virtual DOM。

Note: React.js 使用 Virtual DOM 來追蹤是否元件需要被更新;而 Svelte 沒有使用 Virtual DOM 而是直些更新在 DOM 上。

React vs Svelte 狀態更新差異

功能面向 React Svelte
語法複雜度 使用 Hook,語法稍多 直覺操作變數,語法簡潔
DOM 更新機制 Virtual DOM 比對再更新 編譯階段生成 DOM 操作
狀態更新方式 必須使用 setState / setCount 直接修改變數
更新非同步處理 是,需注意資料一致性 否,變數改變即更新
可讀性與維護性 中等

如果追求極簡語法與優化效能,Svelte 提供了非常流暢的開發體驗。而 React 則擁有強大的生態系與社群支持。

延伸閱讀