跳至主要内容

課程:RN 跨平台開發基礎 第 12 堂:APP 架構規劃

架構健診與優化計畫

在經歷了從渲染原理、導覽架構、狀態管理到效能優化的漫長旅程後,你現在手中握有的不再只是零散的程式碼片段,而是一套完整的 React Native 開發地圖。但理論與實戰之間,往往隔著一個名為「技術債」的深淵。你現有的兩款 APP——人類圖閱讀器與 AuraFlow,雖然已經在封測階段,但它們就像剛蓋好、外表精美卻尚未經過強震測試的建築。

本章的目標,是帶領你進行一次全方位的「架構健診」。我們將不再學習新功能,而是回頭審視你過去三個月的成果。這不僅是為了修補 bug,更是為了將你從一位「看著 AI 生成代碼的執行者」,轉變為一位「能主導 AI 方向的架構師」。

你的 APP 健康嗎?架構健診框架

「能跑」是開發者的及格線,但「能維護」才是專業開發者的分水嶺。請拿出你現有的專案,對照以下這份健診清單,誠實地評估每個部分的健康狀況。

邏輯洩漏:UI 元件是否過於「肥大」?

回憶我們在 Topic 4 討論的 UI = f(state)。健康的架構中,UI 元件應該只負責「長什麼樣子」,而不該負責「資料怎麼來」。

  • 檢查指標:打開一個頁面元件(Screen),如果它的代碼超過 200 行,且裡面充斥著大量的 useEffect、複雜的 data.map 邏輯,或是直接在按鈕的 onPress 寫了十幾行資料處理邏輯,那就是「邏輯洩漏」。
  • 診斷結果:邏輯與 UI 耦合。這會導致你在修改 Android 的排版時,不小心壞了原本正常的邏輯。
  • 優化方向:將邏輯抽離至 Custom Hooks,或移入我們在 Topic 8.2 討論的 Service 層。

導覽黑洞:跳頁時是否全靠「通靈」?

在 Topic 3 與 8.3 中,我們強調了導覽的穩定性。

  • 檢查指標:搜尋專案中的 navigation.navigate('TargetScreen', { id: 123 })。如果這些 Screen 名稱和參數完全沒有 TypeScript 型別保護,而是純字串,那麼當你未來重命名頁面時,編譯器不會報錯,使用者卻會看到閃退。
  • 診斷結果:缺乏型別安全。這是大型專案最容易發生「低級錯誤」的地方。
  • 優化方向:實作 RootStackParamList,確保每一次跳頁都有強型別檢查。

跨平台補丁:是否到處都是 if-else?

在 Topic 5 中,我們學到了系統化處理平台差異的方法。

  • 檢查指標:搜尋程式碼中是否存在大量的 Platform.OS === 'ios' ? ... : ...。特別是當這些邏輯出現在排版樣式(StyleSheet)中時。
  • 診斷結果:隨機性補丁。這種寫法會讓樣式表變得極難閱讀。
  • 優化方向:使用 Platform.select 或是 .ios.tsx / .android.tsx 副檔名分流,將平台差異隔離在專門的檔案中。

效能暗礁:執行緒是否常處於過載?

根據 Topic 7 的執行緒模型,JS Thread 的忙碌直接決定了 APP 的流暢度。

  • 檢查指標:在滑動長列表(如內容列表)時,是否感覺到明顯的掉幀?或是點擊按鈕後要過半秒才有反應?
  • 診斷結果:JS Thread 正在執行重運算,或者發生了不必要的全局 re-render。
  • 優化方向:檢查 FlatList 的優化參數(如 getItemLayout),並利用 React DevTools Profiler 找出是哪個 Context 觸發了多餘的渲染。

內容與媒體類 APP 的關鍵決策

針對你開發的「人類圖閱讀器」與「AuraFlow」,這類 APP 的核心競爭力在於流暢的內容展示穩定的媒體播放。以下是三個你必須做出的架構決策分析。

1. 快取策略:記憶體 vs. 永久存儲

在內容類 APP 中,我們常遇到:文章清單、個人配置、圖片資源。

  • TanStack Query 的定位:它是你的「短期記憶」。適合存放 API 回傳的資料。它的優點是自動處理 re-fetch 與過期機制。
  • AsyncStorage / MMKV 的定位:它是你的「長期記憶」。適合存放「即使沒有網路也要能讀取」的資料,例如使用者的人類圖檔案。
  • 關鍵決策:不要把所有 API 資料都塞進 AsyncStorage。這會讓資料同步變得極其複雜。正確做法是:API 資料歸 TanStack Query,離線存檔與權限設定歸永久存儲

2. 離線支援:閱讀器 APP 的 UX 陷阱

對於人類圖閱讀器,使用者可能會在捷運或飛機上想閱讀之前生成的報告。

  • 工程挑戰:如果使用者在離線時打開 APP,畫面顯示「網路連線失敗」,這是一個差勁的體驗。
  • 優化方案
    • 預載機制:當使用者生成報告時,將文本與關鍵圖片存入本地資料庫(如 SQLite 或簡化的 JSON 存儲)。
  • 優雅降級:利用 NetInfo 監控網路狀態。當斷網時,UI 應顯示「離線模式」,並只展示本地已有的報告清單,而不是讓所有頁面都卡在 Loading 轉圈圈。

3. 多媒體資源管理:AuraFlow 的效能平衡

AuraFlow 涉及音訊播放,這對記憶體與執行緒是極大的挑戰。

  • 載入速度 vs. 穩定性:音訊檔案通常很大。如果你在進入頁面時就一次性載入所有音頻實例(Audio.Sound.createAsync),會導致 UI Thread 卡頓。
  • 最佳實踐
    • 延後初始化:只有當使用者點擊「播放」時,才進行資源載入。
  • 緩衝策略:利用 isBuffering 狀態給使用者明確的視覺回饋(例如播放按鈕變換),避免使用者以為 APP 壞了而重複點擊。
  • 清理機制:在 Topic 3.4 學到的 useFocusEffect cleanup 中,務必呼叫 sound.unloadAsync()。否則,當使用者在不同音訊間切換時,舊的音頻實例會繼續吞噬記憶體,最終導致 APP 崩潰。

制定優化計畫:先摘低垂的果實

面對健診後發現的一堆技術債,你不需要、也不應該一次全部改掉。我們需要一套優先順序矩陣來決定先做什麼。

優先順序矩陣 (Impact vs. Effort)

  1. High Impact / Low Effort (立即行動)
  • 例如:將 FlatListkeyExtractor 設定正確。這只需改一行程式碼,就能大幅提升滑動順暢度。
  • 例如:在 useFocusEffect 加入 cleanup 邏輯,解決語音朗讀停不下來的問題。
  1. High Impact / High Effort (核心重構)
  • 例如:將 API 請求從元件中抽離並導入 TanStack Query。這需要改動大量檔案,但能徹底解決資料不同步的 bug。
  • 例如:導入 TypeScript 定義 Navigation 參數。這能減少 90% 的跳頁報錯。
  1. Low Impact / Low Effort (順手而為)
  • 例如:將 StyleSheet 中的 color: '#FFF' 提取成 theme.colors.white
  1. Low Impact / High Effort (暫時忽略)
  • 例如:為了 1% 的極端效能提升,將所有 JS 動畫重寫為 Reanimated 複雜手勢邏輯(除非那是你的核心功能)。

為什麼「局部重構」勝過「打掉重練」?

很多開發者看到舊代碼很醜,就想直接另開新專案重寫。這通常是災難的開始。 重寫意味著你要重新面對所有已經修過的 bug。科學的做法是:以一個 Feature 為單位進行優化

  • 今天優化「報告列表」:建立 Service 層、導入 TanStack Query、優化 FlatList 參數。
  • 明天優化「設定頁面」:導入 TypeScript、分離樣式常數。 這種「漸進式改進」能確保你的 APP 在優化過程中始終保持「可運行」狀態。

課程大總結:你的 RN 開發心智地圖

這門課程雖然從八個看似獨立的主題出發,但當你站在架構的高度看,它們其實交織成了一個完整的思維閉環。

  1. 底層邏輯(Topic 1, 7):你理解了 JS 與原生的橋接(Bridge/JSI),知道為什麼 JS 不能做重運算。這讓你學會了「尊重執行緒」。
  2. 視覺體現(Topic 2, 5):你掌握了 Flexbox 與跨平台樣式策略。現在你看到一個 UI 稿,腦中會自動拆解成 View 與 Text,並預判 Android 上的陰影落差。
  3. 骨幹連結(Topic 3):Navigation 不再只是跳頁工具,而是 APP 的狀態機。你懂得利用 Lifecycle 來管理資源的啟動與回收。
  4. 大腦中樞(Topic 4, 8):你學會了區分資料的本質。哪些是 UI 狀態,哪些是伺服器快取,哪些是全域配置。你學會了透過「分層」來對抗系統的複雜度。
  5. 原生溝通(Topic 6):相機、通知、檔案匯出不再是黑盒子。你理解了權限請求的節奏,以及 JS 是如何指揮原生部隊作戰的。

從「Coding」到「Architecting」

如果你只是想讓程式碼跑起來,AI (Vibe Coding) 是很好的工具。但如果你想打造一個數萬人使用、持續營運的 APP,你需要的是「控制力」。

透過這門課,你已經具備了審視 AI 輸出內容的能力。當 AI 給你一段寫在 useEffect 裡的複雜 API 調用時,你會皺眉頭並告訴它:「請幫我把這段邏輯抽離到 Service 層,並用 useQuery 封裝。」這就是從「執行者」到「架構師」的轉變。

開發者的旅程才剛剛開始。React Native 的生態系(如 New Architecture 的普及、Expo Router 的進化)瞬息萬變,但底層的原理——執行緒分工、狀態同步、跨平台抽象——是不變的。

保持好奇,持續健診你的程式碼。每消除一個技術債,你就在這條專業道路上往前邁進了一大步。


結業回顧與展望

恭喜你完成了「React Native 跨平台開發基礎」的所有課程!在這一章中,我們將之前學到的零散知識串聯成了一個可執行的架構健診框架。

  • 健診思維:學會辨識邏輯洩漏、導覽黑洞與跨平台補丁。
  • 決策深度:針對內容與媒體應用,理解了快取層級與多媒體資源管理的權衡。
  • 優化路徑:學會使用「影響力/開發成本矩陣」來科學化地安排重構計畫。
  • 思維閉環:確立了從底層渲染到上層架構的完整開發者心智模型。

這門課程旨在為你打下最紮實的地基。雖然教學暫告一段落,但實戰才要開始。你可以帶著這套健診清單,重新審視你的兩個專案,制定出第一個「優化 Sprint」。未來,我們還可以繼續探索 CI/CD 自動化發布、更深層的原生模組開發,或是極端效能優化的領域。

祝你的 APP 封測順利,期待看到它們在應用商店大放異彩的那一天!