1.3 為什麼是 React 與 Expo:宣告式 UI 與跨平台革命#
從命令式到宣告式的典範轉移#
2013 年之前,主流前端框架(jQuery、Backbone)都是命令式的:開發者描述「如何改」介面。React 提出宣告式:描述「介面長什麼樣」,框架自己算出「如何改」。
宣告式的理論優勢:UI 成為狀態的純函數,同一狀態永遠渲染同一介面 —— 這消滅了「狀態與畫面不同步」這一整類 bug,也是函數式程式設計「引用透明(referential transparency)」在 UI 領域的應用。
React 的三個理論支柱#
1. Virtual DOM 與 O(n) Diffing#
直接比較兩棵 DOM 樹是 \(O(n^3)\) 。React 依靠兩個啟發式將其降到 \(O(n)\) :
- 不同型別的元素產生不同的樹(直接重建子樹)
- 同層級以
key標記子元素(列表重排用移動代替重建)
flowchart LR
A[state 變更] --> B[重新執行元件函數]
B --> C[產生新的 Virtual DOM]
C --> D[Diff 舊樹 vs 新樹 O(n)]
D --> E[最小化 DOM 操作]2. 單向資料流(Unidirectional Data Flow)#
資料只能從父元件流向子元件(props),子元件透過 callback 回報。這讓資料流成為有向無環圖(DAG),除錯時可以單向追蹤,不存在雙向綁定的循環依賴問題。
3. 元件組合(Composition over Inheritance)#
UI 被拆成可組合的函數元件,複用靠組合而非繼承 —— 這是物件導向設計原則在 UI 領域的翻轉,也讓元件成為可獨立測試的純函數單元。
為什麼前端需要 TypeScript?#
JavaScript 的動態型別在小型腳本中靈活,但在數萬行的前端應用中成為負債。TypeScript(2012,Anders Hejlsberg,同為 C# 之父)提供結構化型別系統(structural typing) + 漸進式型別(gradual typing):
結構化型別與 JSON 天然契合 —— JSON 物件就是結構型別的值。這是前後端型別共享(4.4 節)能自動化的理論基礎。
Expo:把 React Native 的複雜度藏進約定#
2015 年 React Native 讓「用 React 寫 iOS/Android 原生應用」成真,但原生編譯、憑證簽署、版本升級的痛點讓許多團隊卻步。Expo(2015 年成立)的回答是平台即服務:
| 痛點 | Expo 的解法 |
|---|---|
| Xcode/Android Studio 環境地獄 | 雲端建置 EAS Build |
| 原生模組整合 | expo-* 預封裝模組 + autolinking |
| 版本升級断裂 | SDK 受控升級路徑 |
| 無法寫原生碼? | Development Build 允許 eject 原生層 |
抽象層次的取捨:Expo 蓋掉平台差異,代價是初期對底層控制較少;但 2020 年代 Exno 的 development build 已允許「需要時下沉到原生」,抽象不再是單行道。
本書的選型組合#
flowchart TB
subgraph 前端
E[Expo] --> RN[React Native]
RN --> R[React]
R --> TS[TypeScript]
end
subgraph 後端
AX[Axum] --> TW[Tower]
TW --> T[Tokio]
T --> RS[Rust]
end
TS <-->|JSON + 自動型別| RS選擇的邏輯:
- React:宣告式 UI 是當代 UI 開發的共識正解。
- TypeScript:為跨邊界型別共享提供可能。
- Expo:以最低維運成本同時覆蓋 Web 與行動裝置。
- Rust/Axum:以最高可靠性與效能承載 API。
- 共同語言 JSON:兩端型別系統都對 JSON 序列化有第一級支援。
習題#
- 解釋 Virtual DOM 為何存在。若目標平台是原生 View 而非 DOM,同樣思想如何適用?
- 結構化型別系統如何使「後端 Rust struct → 前端 TypeScript interface」的自動轉換成為可能?
- 比較 Expo 管理式工作流程(managed workflow)與裸工作流程(bare workflow)的抽象取捨。