試用實驗階段的 React Compiler
原文由 Alex O'Callaghan 于 發布,訂閱此部落格
實驗階段的 React Compiler 已經開源,需要搭配 React 19 的 beta 版本才能使用。編譯器透過對 JavaScript 語意與 Rules of React 的理解,自動套用 memoization 來提升效能。這可以取代透過 useMemo、useCallback 與 React.memo 進行手動 memoization 的需求。
我決定在我們的 microfrontend shell 應用程式中試試這個編譯器。它負責將多個 microfrontend 整合成單一應用程式,因此提升效能對整個平台的使用者體驗可能會有很大的影響。裡面也有幾處用到了 useMemo 和 useCallback,我很想看看用了編譯器之後能不能把這些拿掉。
健康檢查
有一個 react-compiler-healthcheck 套件可以用來檢查你的程式碼基底是否與編譯器相容。
我用 npx react-compiler-healthcheck 執行它,結果相當令人鼓舞:
Successfully compiled 43 out of 45 components.
StrictMode usage found.
Found no usage of incompatible libraries.
ESLint 外掛
還有一個 ESLint 外掛可以獨立於編譯器使用。
我把 eslint-plugin-react-compiler 加到我們的 ESLint 設定中,然後執行了 ESLint。
就沒那麼順利了—— ESLint 拋出了一個錯誤:
TypeError: Error while loading rule 'react-compiler/react-compiler': Cannot read properties of undefined (reading 'endsWith')
Occurred while linting /home/aocallaghan/dev/frontend-app-shell/.eslintrc.js
我試著指定不同的檔案(例如只針對我們的 React 元件),但它在遇到的第一個檔案就報錯了。造成問題的是這一行:
if (context.filename.endsWith(".tsx") || context.filename.endsWith(".ts")) {context.filename 並沒有被定義,但 filename 這個變數在上一層作用域中已經定義好了。我在本地改成使用 filename 變數後,就一切正常且沒有錯誤地通過了。
後來發現這是一個已經修復的 bug:github.com/facebook/react/pull/29104
與 Babel 整合
我們使用 Webpack + Babel 來打包應用程式。加入 babel-plugin-react-compiler 似乎是最簡單的選項。我更新了 babel.config.js,按照文件中的說明,將這個外掛放在第一個順位。
在這裡我遇到了解析 react/compiler-runtime 的錯誤——這是預期中的,因為我們需要使用 React 19 的 beta 版本。
我升級到 React 19:
npm install react@beta react-dom@beta
Webpack 建置成功了。但現在應用程式一片空白,主控台也出現了錯誤:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'ReactCurrentDispatcher')
簡單 Google 搜尋一下,發現這似乎是 react 和 react-dom 版本不一致時常見的錯誤。我試著使用 Yarn 的 resolutions 設定來強制所有依賴都使用 React 19,但在重新產生 yarn.lock 並重新安裝 node_modules 後,執行時依然報錯。
追蹤錯誤後發現,問題出在我們用來做 OAuth2 驗證的 react-oidc 套件上。這個套件在打包時把 react-jsx-runtime 一起包進去了,這就是版本不一致的來源。我對 vite.config.ts 做了一些本地修改,然後在本地重新建置了這個套件。
我也發了一個 issue 請上游修復這個問題(github.com/AxaFrance/oidc-client/issues/1370)。
接著又出現了另一個不同的錯誤:
Uncaught (in promise) TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_0__.createFactory) is not a function
createFactory 已經在 React 19 中被移除。這個錯誤來自 recompose 套件,它是被我們一些內部套件所引入的。recompose 自從 React Hooks 推出後就已被棄用,只是我們一直沒有處理這個依賴。
我查看了仍在使用 recompose 的兩個套件:
- 一個雖然列為依賴,但其實已經完全沒在用了,我就把這個未使用的依賴移除了
- 另一個主要是用來設定 defaultProps——我測試應用程式時不需要這些元件真的能運作,所以就先把相關程式碼和依賴移除,並註記之後要好好修正
接著程式碼本身還有最後一個錯誤——我們還在呼叫 ReactDOM.render,現在已經被 createRoot 取代了。很快就修好了。
大功告成!應用程式可以正常渲染和運作了!
效能評估
我使用 React Developer Tools Profiler 做了快速的前後對比。
- 在加入 React Compiler 之前,初次渲染其中一個應用時有 20 次 commits,加入後降到了 16 次 commits
- 我把應用程式中所有的
useCallback和useMemo用法都移除後,初次載入時仍然只有 17 次 commits
開發者工具還會標示出編譯器已自動幫你 memoize 元件渲染的地方:

隨機一篇部落格
留言
登入後參與討論