iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0

前情提要

走到這裡,這個關於 Signal 與 Fine-grained Reactivity 的系列文章,暫時告一個段落。
這篇不談新的技術細節,而是一些我的心得與反思。

Ryan Carniato 的影響

這整個系列,某種程度上是受到 Solid.js 作者 Ryan Carniato 的啟發。
他總能一針見血地指出我們在 React 開發中面臨的痛點。
作為一個資深 React 工程師,我常常覺得「對,這就是我每天遇到的問題!」。

Solid.js 本身無疑是一個優秀的框架,但對新手而言門檻不低。
不過,對我來說,它所做的很多設計選擇,比 React 的發展方向更合理,比如: 去掉 dependenices array 的 effect、讓 Mounted 與 Cleanup 獨立開來、拔掉 V-DOM 的 JSX...,這些都是之前 React 社群裡呼聲很高但不被重視的需求。

React 與 Next.js 的困境

這幾年 React 的走向越來越受到 Vercel 的影響。
Server Components 被強推,讓前端工程師不得不接受還不成熟的模式。

老實說,我反而比較懷念「沒有 Server Components 的 Next.js」,那個時代的 React 更單純,缺點雖然明顯,但至少我們能自由選擇解法。

社群裡有人提出過「React 是否應該引入 signal」甚至「考慮無 VDOM 版本」,但這可能與金主 Vercel 的利益衝突。

結果,我看到的,是一種 React 末日餘暉的樣態。

雖然像 TanStack 還在努力支撐,但如果未來出現成熟的替代方案,我大概也不會再選 Next。

常見誤解

你這不就 Jotai?

社群上有時會聽到一些說法,認為 Jotai(或 Atomic 模型)和 Signal 的做法相同,而且因為依附框架生態,更加友好。
但如果你跟著這系列文章一起實作,或曾經實際動手實作過,就能理解兩者其實有著截然不同的設計理念,關鍵差異在於「是否處理依賴關係」。

下面我簡單對比一下兩者概念上的差異。

Atomic(Recoil / Jotai 那一派)

  • 核心概念:把狀態切分成最小單元(state atom),彼此之間沒有隱含的依賴追蹤。
  • 組合方式:靠「selector / 派生函數」來管理邏輯與組合。
  • 更新模式:狀態改變時,不會自動往下通知「依賴者」,而是重新執行 selector(純函數重新計算)。
  • 特點
    • 容易以函數式的方式理解(狀態 = 值,selector = 純函數)。
    • 但「依賴圖」不顯性存在 → 每次取值都需要重新計算,可能會造成重複計算。

Signal

  • 核心概念:同樣是細粒度的狀態單元,但內建顯式依賴追蹤圖。
  • 組合方式computed / effect 會在執行時自動註冊依賴 → 之後來源值變動時,自動通知下游。
  • 更新模式:push-based,來源值一改,下游自動標記 stale,等 scheduler 決定何時執行更新。
  • 特點
    • 可以避免不必要的重算(因為知道誰依賴誰)。
    • 更新的傳播更快、更精準。
    • 但設計上需要 runtime 的 graph 管理。

對比整理

一句話比較兩者概念上的差異:

  • Atomic:切分狀態,但不處理依賴 → 需要用函數「再算一次」。
  • Signal:切分狀態,還加上依賴追蹤 → 誰需要更新,系統自己知道。

不處理依賴關係,寫起來確實很輕鬆;而且 Jotai 採用框架本身提供的狀態單元來管理,天然就能符合各框架的生命週期,避免同步問題。
但相對地,這樣的模式必須「靠框架 re-render」來保證正確性,而不像 Signal 能透過 runtime 的依賴追蹤做到更細粒度的更新。

流程圖差異

https://ithelp.ithome.com.tw/upload/images/20250910/20129020yE4rYMHmUL.png

啊不就 DI(Dependency Injection 依賴注入)嘛?

常常有人把 Signal 與 Vue/React 的整合,類比成傳統 OOP 世界的 Dependency Injection (DI)。
表面上看起來確實有一點像:把外部狀態「注入」到框架內使用。

但本質差異在於:

  • DI 解決的是 物件依賴 的組合與管理。
  • Signal 解決的是 資料依賴 的追蹤與更新時序。

看似相似,其實解決的維度完全不同。

DI 解決什麼?

  • 解決:物件之間「誰需要誰」
  • 時機:建構時
  • 關鍵字:依賴關係、組裝物件
  • 範例:Car 需要 Engine,由 DI 框架幫你塞進去
class Engine {}
class Car {
  constructor(private engine: Engine) {}
}

Signals 解決什麼?

  • 解決:資料之間「誰依賴誰」
  • 時機:執行時
  • 關鍵字:資料追蹤、狀態更新
  • 範例:totalPrice 依賴 count * unitPrice,自動跟著變
const count = signal(2);
const unitPrice = signal(100);
const totalPrice = computed(() => count.get() * unitPrice.get());

簡單釐清

  • DI:幫你解決「物件怎麼拿到需要的服務」。
  • Signals:幫你解決「資料變了,誰要跟著更新」。

Signal 只是新的 state management

很多人以為 Signal 只是新的 state management,但經過我們這系列深入的實作,你會發現它所觸及的領域,不僅僅只是狀態管理工具這麼簡單。

真正讓人恐懼的,是它逼我們去反思 VDOM 是否仍然必要。

一旦這種思維普及,過去圍繞在 VDOM 的知識體系與教學產業鏈,就會被動搖。
這也是為什麼有些人會本能地排斥,甚至貶低。

技術的演進,從來不只是程式碼的事,也是利益結構的事。
Signal 真正動搖的,不是 state,而是整個 VDOM 信仰。

心態調適:面對不理性的攻擊

有些人會直接否定 Signal,甚至用嘲諷的語氣說:「Signal 沒用啦!」、「Dan 都叫你別用!」
這種言論常常帶有情緒或立場色彩,而不是基於對技術本身的理解。

對我而言,這些聲音並不構成威脅,反而像是一面鏡子:

  • 如果你已經理解 Atomic 與 Signal 的差異,就能看出對方的盲點。
  • 如果你還沒搞懂,那就是一個很好的提示: 該深入研究了

所以,遇到這類攻擊時最好的態度是 不急於反駁,而是回到程式碼與設計原理本身。

當你能用簡單的範例解釋「依賴追蹤的差異」時,這些嘲諷自然就失去力量。

signal 的未來

基本上都是很看好的,從去年的 TC-39 signal proposal 就不難看出它在前端應用的地位是越來越重要了,除了 React 還在營造「大哥是對的」的氛圍外,其餘主流框架全都導入 signal 應用進入新的紀元,比如:Vue 的 Vapor mode、Angular 17+ 的 signal、Svelte rune、preact signal、solidjs ...,有的甚至已經在往拔除不需要的 V-DOM (EX:Vue 的 Vapor mode、solidjs JSX setting) 方向邁進。

所以能掌握這個概念的核心,在未來的應用場景就能比較得心應手。

以我自己為例,掌握這個概念之後我跳轉不同框架時,就非常容易上手。

研究與寫作的動機

會開啟這個系列,其實是因為我在開發自己開源的 Signal System Library -- segnale-react
在這個過程中,我不斷遇到挑戰,才發現:
過去在學校或面試題裡那些「演算法與資料結構」的東西,原來在這裡都能派上用場。

這也讓我更確信:

想設計好框架的底層,就必須掌握 JS 基礎與計算機科學的知識。

收穫與體會

這個系列對我來說,不只是技術筆記,更是一段心路歷程:

  • 它源自於對 React 的不滿
  • 因 Ryan 的啟發而展開
  • 最後則落回到 JS 基礎與算法 的重要性

最大的體會是:

框架會更替,但基礎知識與思維模式才是能走得更遠的東西。

這系列文章,還僅僅只是扒開框架引擎裡的第一層 Reactive Core,當然也是每個框架最為核心的基石,如果要往下延伸,還會遇到 DOM Render / UI Render Scheduler / Component Model 等問題,每個框架都有選擇上的考量和取捨,這部分應該會是我日後研究的方向吧!

給讀者的建議

如果你正在學習 React,其實不需要急著跳到 Solid.js 或其他框架。
因為真正重要的不是「框架選擇」,而是理解底層觀念:

  • state → derivation → effect 的資料流
  • scheduler 與依賴圖管理的必要性
  • push vs pull、eager vs lazy 的差異

只要掌握這些,你就能在任何框架裡快速找到方向。

別只學會用框架,更要理解它的底層邏輯。

潮流會變,但基礎概念才是工程師能帶走的真正資產。

Signal 實作對照

這邊還是附上系列文章中,實作的程式碼給大家參考,這還有包含每個段落的 Unit test,但只針對有異動的部分。

基本上還是希望讀者們自己參考我的範例去更改,不要只是整段複製貼上,這樣一來你會失去很多細節思考的機會。

我提供的範例是有經過考量才選擇的做法,很多時候在資料結構與訂閱制度的選擇上,未必符合所有開發需求,但會比較讓初學者容易理解概念,不會跳來跳去切換不同的算法和資料結構,導致講解過程中不必要的錯亂。

比較進階的探討會聚焦在 Ryan Carniato 這個系列文章的內容,也是目前主流 Signal 發展的取捨。

總結

最後,分享一段我很喜歡的港片橋段,搶錢夫妻的那段最後的播報:

他說什麼,你什麼都相信了,那麼你們有沒有懷疑過,他們可能也在騙你,也許是假的,也許他也是不能肯定的,也許也跟我和電視台一樣,為了能多賺點錢,多賺點收視率,這麼簡單為甚麼你沒有留意呢?

電視台給我們看什麼,我們就看什麼,報紙寫什麼我們就相信什麼,偶像穿什麼,我們就穿些什麼,廣告說什麼好吃,我們就把他們都買回來,大家都沒有用腦子對不對,反正你說什麼我們就做什麼;一個人穿牛仔褲,這世界都穿牛仔褲了,這個世界只有牛仔褲了嗎? 不可能嘛!

你們是傳播界老大,你們說什麼我們當然相信了,那麼坐在家裏面打開電視機,叫我們相信什麼說什麼,我們懂什麼呢? 話不是這麼說,你們要用思考,不能光靠眼睛和耳朵,一定要用腦袋想想,我覺得能靠的就是這個了。

這段雖然是呼籲我們要帶著腦子看新聞,但放在開發領域又何嘗不是呢?

Youtuber 給我們看什麼,我們就看什麼,AI 寫什麼我們就相信什麼,線上課程教什麼,我們就用些什麼,廣告說什麼好用,我們就把技術全部轉移過去...,一個人用 React,這世界都用 React,這個世界只有 React 了嗎? 不可能嘛!

希望這系列文章,能帶給大家用不同角度思考,重新審視那些既定的規則與假設,跳脫原本的思想框架,能更清楚的認知到,我們所用的工具在解決什麼必要的需求,不要只是盲從。


上一篇
進階內核(VII):DevTools 與診斷
系列文
Reactivity 小技巧大變革:掌握 Signals 就這麼簡單!30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
nihilitypeo
iT邦新手 3 級 ‧ 2025-09-30 11:19:10

看得很過癮,謝謝這三十天的分享

我要留言

立即登入留言