iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Modern Web

React 從 0.5 到 1系列 第 11

[鐵人賽 Day11] React 原始碼的初見面 ——官方 codebase 指南

前言

為了更近一步理解平常使用的 useState, useEffect, memo...等機制的運作,我嘗試下載了 React 的原始碼,沒想到初次見面就讓人手足無措。幸好官方提供了一些給開源貢獻者的指南,跟隨著官方的文件,可以省下不少力氣。

底下的內容會跟著 React 的文件,認識原始碼的大致架構。並且附上 IDE 的截圖,讓各位更好地想像。

最上層的資料夾

packages 裡包含了所有 React 專案內的 packages 的 metadata(例如:package.json)以及 source code( src 子目錄)。

fixtures 裡面包含了幾個讓貢獻者可以使用的測試工具。

build 資料夾裡面有專案 build 出來的東西。

其他的資料夾大部分是工具相關,貢獻者通常不會需要處理到、或者遇到跟這些資料夾相關的議題。

註:有另一個名稱相似的專案 https://github.com/reactjs/reactjs.org 放的是 React 相關的文件。放 Source code 的專案則是 https://github.com/facebook/react

(我的專案 build 不起來,所以少了其中一個資料夾。除了 build,頂層資料夾就是這些。)

https://ithelp.ithome.com.tw/upload/images/20210921/20140045WVuH1Scipn.png

拋出錯誤的方式與 Invariants 模組

React 專案使用 console.error 來表示警告,只有在開發環境中才會顯示,在正式環境中則是完全看不見。如下圖:

https://ithelp.ithome.com.tw/upload/images/20210921/20140045Cigh0dMCUL.png

你還可以使用專案裡的  invariant 模組。當情境是 false 的時候,Invariant 就會被拋出。你可以把這個功能想像成在做一個斷言(assertion)。如下圖:

https://ithelp.ithome.com.tw/upload/images/20210921/20140045NGNqoKMnUO.png

與上面不同的是,Invariant 在開發與正式環境中都會運行,只是在正式環境中,error message 會被自動的替換成 error code 來避免對 byte size 的負面影響。

multiple packages

React 是一個 monorepo。在同一個 repo 中管理多的模組的好處在於,方便統一管理 depencency、版號、流程,以及因為東西都放在一起,大規模的重構時會更容易,這些模組間的改變也可以互相協調。

React Core 核心要素

React 的核心包含所有 top-level 的 API,僅僅包含那些定義元件所必須的 API,不包含演算法或者任何 platform-specific 的 code。這些 API 會被 React DOM 以及 React Native 元件二者使用。React core 的內容位於 packages/react :底下的截圖中,可以看到一些眼熟的 export createElementComponentChildren ... etc。

https://ithelp.ithome.com.tw/upload/images/20210921/20140045oBhUn12kyd.png

順著 import export 的路線往下追,可以找到一些關於這些 core API 如何運作的線索。

https://ithelp.ithome.com.tw/upload/images/20210921/20140045tOcRfSFO6H.png

Event System

React 運用了一個事件系統來調整原生的事件,減緩不同瀏覽器之間的差異。

https://ithelp.ithome.com.tw/upload/images/20210921/20140045OhdgOmI3Eo.png

Reconcilers

即使是差異極大的 renderers 例如 React DOM 與 React Native,也會需要使用許多相同邏輯。特別是 React 使用的 reconciliation algorithm 演算法也應該要盡可能地相似,讓 declarative rendering, custom components, state, lifecycle methods, 跟 refs 的運作在不同平台上的運作前後一致。

不同的 renderers 所共有的 code,我們稱呼這個部分叫做 reconciler。當一個更新例如 setState() 被觸發的時候,reconciler 會去呼叫元件上的 render(),然後對他們進行 mount, update, unmount 這些動作。

Reconciler 聽起來太抽象嗎?請參考之前關於 reconciliation 的文章:https://ithelp.ithome.com.tw/articles/10268531/

Fiber Reconciler

fiber 是用來解決前一版 stack reconciler 內既有的問題,以及一些長期存在的錯誤。React 16 之後就成了預設的 reconciler。他的 source code 可以在 react-reconciler 中找到。

https://ithelp.ithome.com.tw/upload/images/20210921/20140045VyOKoFmIrg.png

小結論

看完這些介紹之後,大概可以抓到如果想要理解例如 React.memo 的處理,會需要查找的資料夾有 packages/react 關於 React.memo 的內容,以及 packages/react-reconciler` 當中,可能有對於比較 prevProps 和 nextProps 判斷機制的描寫。

Ref

https://reactjs.org/docs/codebase-overview.html

https://reactjs.org/docs/implementation-notes.html


上一篇
[鐵人賽 Day10] Context(下)-花式用法
下一篇
[鐵人賽 Day12] 來讀 Hooks FAQ 文件吧! - Hooks 取代 render props 跟 HOC 的用法了嗎?
系列文
React 從 0.5 到 115

尚未有邦友留言

立即登入留言