📋 目錄
SolidJS 2.0 Beta 來了,Slogan 是「The Suspense is Over」。這個口號的背後,是 SolidJS 團隊對 Async Rendering(非同步渲染)問題的一次全面回應。SolidJS 一直以「無 Virtual DOM + Fine-Grained Reactivity = 效能極致」著稱,但 Async 場景(Server Components 時代的剛性需求)一直是它的弱項。2.0 Beta 的 Async Primitives 和 Dev Guardrails,試圖改變這件事。
前端工程師為什麼要關心 SolidJS 2.0
SolidJS 長期以來處於「效能最強,但人氣遠不如 React/Vue」的狀態。它的 Fine-Grained Reactivity 模型(狀態變化只更新實際用到的 DOM 節點,不需要 Virtual DOM diffing)在 benchmark 上碾壓所有對手,但學習曲線和社群規模的劣勢,讓多數團隊選擇了更容易找到人才的 React。
SolidJS 2.0 Beta 這次不只是在現有模型上做改進——它試圖解決一個 SolidJS 一直以來的痛點:Async 渲染的 DX(Developer Experience)問題。
過去在 SolidJS 裡處理非同步資料,需要手動管理 createResource、處理 loading/error 狀態,沒有 React Suspense 那樣的宣告式模型。2.0 的 Async Primitives,就是要把這個 DX 補上。
SolidJS 的核心:Fine-Grained Reactivity
SolidJS 與其他框架最根本的差異,在於它的響應式系統不是在 Virtual DOM 層運作,而是在編譯時就確定了精確的依賴追蹤。
SolidJS 的 Signal 運作方式
import { createSignal, createEffect } from 'solid-js';
// createSignal 創建一個 reactive state
const [count, setCount] = createSignal(0);
// createEffect 追蹤 count 的讀取,自動建立依賴
createEffect(() => {
console.log('Count changed:', count());
});
// 輸出:Count changed: 0
setCount(1);
// 輸出:Count changed: 1
setCount(2);
// 輸出:Count changed: 2
關鍵:SolidJS 的 count() 是個 function,讀取它就是在建立依賴追蹤。這個設計讓 SolidJS 在編譯時就能知道「這個 effect 依賴 count」,然後在 count 變化時,只執行這個 effect。組件本身不需要 re-render。
// SolidJS:當 count 變化時,只有這個 span 的 textContent 更新
// 整個 <Counter /> 組件不會 re-render
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
{/* count() 的讀取在編譯時就建立了 */}
<span>{count()}</span>
<button onClick={() => setCount(c => c + 1)}>加一</button>
</div>
);
}
對比 React 的話:如果用 React 的寫法,count 變化時,整個 <Counter /> 組件函式會重新執行,React 要對比 Virtual DOM,決定要更新什麼。SolidJS 跳過了這一步。
SolidJS 2.0 Beta 的核心新特性
1. Async Primitives:非同步的宣告式處理
SolidJS 2.0 Beta 最重要的功能。過去處理非同步資料,是 SolidJS 生態系最大的痛點之一:
// SolidJS 1.x:手動管理 Resource
import { createResource, Show } from 'solid-js';
function UserProfile({ userId }) {
const [user] = createResource(userId, async (id) => {
return fetch(`/api/users/${id}`).then(r => r.json());
});
return (
<Show when={!user.loading} fallback={<div>載入中...</div>}>
<Show when={!user.error} fallback={<div>載入失敗</div>}>
<div>{user().name}</div>
</Show>
</Show>
);
}
SolidJS 2.0 的 Async Primitives 讓這個模式更加宣告式:
// SolidJS 2.0 Beta:Async Primitives
import { createAsync, Suspense } from 'solid-js';
async function fetchUser(id) {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
function UserProfile({ userId }) {
// createAsync:建立一個非同步的 reactive 資料來源
const user = createAsync(() => fetchUser(userId()));
return (
<Suspense fallback={<div>載入中...</div>}>
<div>{user()?.name}</div>
</Suspense>
);
}
createAsync 接受一個回傳 Promise 的 function。user() 在模板中被讀取時,SolidJS 自動建立 Suspense boundary 處理 loading 狀態。
這個改變的意義:SolidJS 2.0 補上了非同步 DX 的最後一塊拼圖。以後處理 Server Components、Streaming SSR、Async Data Fetching,不需要再學習專屬的 createResource API。
2. Dev Guardrails:開發時的錯誤警告
Dev Guardrails 是 SolidJS 2.0 引入的開發時警告機制,幫助開發者捕捉「在 reactive scope 內意外讀取非同步值」這類常見 bug。
// SolidJS 1.x:這個 bug 不容易發現
function UserPosts({ userId }) {
const [posts, setPosts] = createSignal([]);
// 這個 effect 讀取了 posts(),建立了依賴
createEffect(() => {
// 這裡 posts() 的讀取是同步的
console.log(posts());
});
// 如果你在這裡不小心讀取了某個 async 資源...
// 沒有警告,但可能造成隱性的 reactive bug
}
SolidJS 2.0 的 Dev Guardrails 會在編譯時或開發模式下,警告你:
// SolidJS 2.0 Dev Guardrails:
// 如果你在 reactive scope(effect/computed)裡讀取了 async value
// 會收到警告:「非同步值不應該在同步 reactive scope 內被讀取」
// 這個設計讓 SolidJS 的 reactive 模型更加嚴謹,防止隱性 bug
3. @solidjs/signals:新響應式基礎
SolidJS 2.0 將 @solidjs/signals 獨立為一個 Package,讓 SolidJS 的響應式核心可以脫離 SolidJS 框架單獨使用。
// @solidjs/signals 可以單獨使用
import { signal, computed } from '@solidjs/signals';
const count = signal(0);
const doubled = computed(() => count() * 2);
console.log(doubled()); // 0
count(5);
console.log(doubled()); // 10
這個變化的意義:Signals 是 2024-2026 年前端效能優化的重要方向。Vue 的 Vapour Mode、Angular 的 Signals、SolidJS 的 Signal 基礎——都在朝同一個方向走。SolidJS 把信號系統獨立出来,讓它成為一個可以給任何框架用的基礎庫。
SolidJS 的效能:為什麼它碾壓所有對手
SolidJS 的效能優勢來自一個簡單的事實:它不跟 Virtual DOM 合作。
React 的渲染流程:狀態變化 → 組件函式重新執行 → 生成新 Virtual DOM → 與舊 Virtual DOM 比對差異 → 更新實際 DOM。
SolidJS 的渲染流程:狀態變化 → 只更新「讀取過這個狀態」的 DOM 節點。
// React:count 變化 → <Counter /> 整個重新執行
// 即使只有 <span> 需要更新,其他兩行也會執行
function Counter() {
const [count, setCount] = useState(0);
console.log('Counter re-rendered!'); // 每次都執行
return (
<div>
<span>{count}</span> // 只有這行需要真的更新 DOM
<button onClick={() => setCount(c => c + 1)}>加一</button>
</div>
);
}
// SolidJS:count 變化 → 只有 <span> 的 textContent 更新
// <Counter /> 函式只執行一次
function Counter() {
const [count, setCount] = createSignal(0);
console.log('Counter ran once!'); // 只在初始化時執行一次
return (
<div>
<span>{count()}</span> // count 變化時,SolidJS 直接更新這個 span
<button onClick={() => setCount(c => c + 1)}>加一</button>
</div>
);
}
SolidJS 適合誰
SolidJS 擅長的場景
- 效能敏感型應用:遊戲引擎、資料視覺化、複雜儀表板
- 元件庫作者:SolidJS 編譯出的 DOM 更新最少,適合底層元件庫
- 對效能有堅持的團隊:SolidJS 的效能保証是編譯器給的,不需要手動 memoize
SolidJS 不擅長的場景
- 需要快速找到人才:SolidJS 開發者數量遠少於 React
- 大量依賴第三方 UI 庫:SolidJS 生態系的元件庫豐富度不如 React
- 需要大量使用 Server Components:SolidJS 2.0 的 Async Primitives 是beta,生態系還在追趕
SolidJS 2.0 遷移評估
SolidJS 2.0 Beta 的 API 變化相对温和,多數 1.x 的 code 只需要小幅調整:
| 1.x | 2.0 | 變化 |
|---|---|---|
createResource | createAsync | 新的 Async 語法,建議新專案直接用 |
Show / Switch | 大致不變 | 底層改進,API 不變 |
createEffect | 可能需要調整 | Dev Guardrails 會警告不正確的使用 |
SolidStart 2.0(SolidJS 的全端框架)也在 alpha 中。如果你是 SolidJS 用戶,2.0 是一個值得開始測試的版本。
結語
SolidJS 2.0 Beta 補上了 SolidJS 長期以來的 Async DX 痛點,同時把 Signal 系統獨立出来,让它成為一個更通用的響應式基礎。
對於關心前端效能的工程師,SolidJS 2.0 的信號系統演化值得關注——2026 年會是 Signal 概念全 Framework採用的關鍵年。SolidJS 的 Signal 與 Vue 的 Vapour Mode、Angular 的 Signals,都在往同一個方向走:讓響應式更精確、更編譯器友好。
SolidJS 不是多數專案的框架選擇,但它代表的方向,會影響所有框架。
*## 延伸閱讀
- 2026 前端框架比較:React、Vue、Svelte 誰與爭鋒 — 框架選擇的完整評估
- Svelte 5 Runes 深度解析 — 另一個 Fine-Grained Reactive 框架
本文是「2026 前端框架選擇」系列文章之一。*