React 編譯器

在這里插入圖片描述

🤖 作者簡介:水煮白菜王,一位前端勸退師 👻
👀 文章專欄: 前端專欄 ,記錄一下平時在博客寫作中,總結出的一些開發技巧和知識歸納總結?。
感謝支持💕💕💕
本文內容參考自 React文檔 - React Compiler 內容進行記錄和整理?

目錄

  • React 編譯器
    • 編譯器是做什么的?
      • 注意
      • 深入探究
      • React Compiler 添加了什么樣的記憶?
        • 優化重新渲染
        • 昂貴的計算也會被記憶化
    • 開始使用
      • 安裝 eslint-plugin-react-hooks
      • 將編譯器推出到您的代碼庫
      • 現有項目
      • 新項目
      • 在 React 17 或 18 中使用 React 編譯器
      • 在庫上使用編譯器
    • 用法
      • Babel
      • Vite
      • Next.js :
      • Remix
      • Webpack
    • 故障 排除
      • 編譯器假定什么?
      • 如何知道我的組件已優化?
      • 編譯后某些內容無法正常工作
  • 如果你覺得這篇文章對你有幫助,請點贊 👍、收藏 👏 并關注我!👀

React 編譯器

本文將為你介紹 React Compiler 以及如何成功試用它

本文您進入React 編譯器將學習
編譯器入門
安裝編譯器和 ESLint 插件
進行故障排除

注意
React Compiler 是目前在 RC 中的一個新編譯器,React已經開源了它以從社區獲得反饋。現在建議大家試用編譯器并提供反饋。
最新的 RC 版本可以通過標簽找到,每日實驗版本可以使用 .@rc@experimental

React Compiler 是React開源的一個新的編譯器,用于從社區獲取反饋。它是一個僅限構建時的工具,可自動優化您的 React 應用程序。它與純 JavaScript 一起工作,并且理解 React 的規則,因此你不需要重寫任何代碼來使用它。

eslint-plugin-react-hooks 還包括一個 ESLint 規則,該規則直接在編輯器中顯示來自編譯器的分析。React強烈建議大家立即使用 Linter。Linter 不需要您安裝編譯器,因此即使您還沒有準備好試用編譯器,也可以使用它。

該編譯器目前作為 發布,可以在 React 17+ 應用程序和庫上試用。要安裝 RC:rc
npm

npm install -D babel-plugin-react-compiler@rc eslint-plugin-react-hooks@^6.0.0-rc.1

yarn

yarn add -D babel-plugin-react-compiler@rc eslint-plugin-react-hooks@^6.0.0-rc.1

編譯器是做什么的?

為了優化應用程序,React Compiler 會自動記住你的代碼。您現在可能熟悉通過 API 進行記憶化,例如 、 和 。通過這些 API,你可以告訴 React 如果它們的輸入沒有改變,你的應用程序的某些部分就不需要重新計算,從而減少了更新的工作。雖然功能強大,但很容易忘記應用記憶化或錯誤地應用它們。這可能會導致更新效率低下,因為 React 必須檢查沒有任何有意義的更改的 UI 部分。useMemouseCallbackReact.memo

編譯器利用其 JavaScript 和 React 規則的知識來自動記住組件和 hook 中的值或值組。如果它檢測到規則的破壞,它將自動跳過這些組件或 hook,并繼續安全地編譯其他代碼。

注意

React Compiler 可以靜態檢測何時違反 React 規則,并安全地選擇退出僅優化受影響的組件或鉤子。編譯器沒有必要優化 100% 的代碼庫

如果您的代碼庫已經很好地記住了,您可能不希望看到編譯器的性能有重大改進。但是,在實踐中,記住導致性能問題的正確依賴項是很棘手的。

深入探究

React Compiler 添加了什么樣的記憶?

React Compiler 的初始版本主要專注于提高更新性能(重新渲染現有組件),因此它專注于以下兩個用例:
1.跳過組件的級聯重新渲染

  • 重新渲染會導致其組件樹中的許多組件重新渲染,即使只有更改<Parent /><Parent />

2.跳過 React 外部的昂貴計算

  • 例如,在需要該數據的組件或 hook 內部調用expensivelyProcessAReallyLargeArrayOfObjects()
優化重新渲染

React 允許你將你的 UI 表示為當前狀態的函數(更具體地說:它們的 props、state 和 context)。在當前的實現中,當組件的狀態發生變化時,React 將重新渲染該組件及其所有子組件 — 除非你使用 、 或 應用了某種形式的手動記憶。例如,在下面的示例中,每當 的狀態發生變化時,都會重新渲染:useMemo() useCallback() React.memo() <MessageButton><FriendList>

function FriendList({ friends }) {const onlineCount = useFriendOnlineCount();
if (friends.length === 0) {return <NoFriends />;}return (<div><span>{onlineCount} online</span>{friends.map((friend) => (<FriendListCard key={friend.id} friend={friend} />))}<MessageButton /></div>);
}

React Compiler 會自動應用等同于手動記憶化的作,確保只有應用程序的相關部分會隨著狀態變化而重新渲染,這有時被稱為“細粒度響應性”。在上面的例子中,React 編譯器確定 of 的返回值即使作為更改也可以重用,并且可以避免重新創建這個 JSX,并避免在 count 發生變化時重新渲染。<FriendListCard />friends<MessageButton>

昂貴的計算也會被記憶化

編譯器還可以自動 memoize 渲染期間使用的昂貴計算:

// **Not** memoized by React Compiler, since this is not a component or hook
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }// Memoized by React Compiler since this is a component
function TableContainer({ items }) {// This function call would be memoized:const data = expensivelyProcessAReallyLargeArrayOfObjects(items);// ...
}

但是,如果確實是一個昂貴的函數,你可能需要考慮在 React 之外實現自己的記憶化,因為:expensivelyProcessAReallyLargeArrayOfObjects

  • React 編譯器只記住 React 組件和鉤子,而不是每個函數
  • React Compiler 的記憶不會在多個組件或 hook 之間共享

因此,如果用于許多不同的組件,即使傳遞了完全相同的項目,也會重復運行昂貴的計算。建議先進行分析,看看它是否真的那么昂貴,然后再使代碼變得更復雜。expensivelyProcessAReallyLargeArrayOfObjects

開始使用

安裝 eslint-plugin-react-hooks

React Compiler 還為 ESLint 插件提供支持。你可以通過安裝 eslint-plugin-react-hooks@^6.0.0-rc.1 來試用。

npm install -D eslint-plugin-react-hooks@^6.0.0-rc.1

ESLint 插件將在編輯器中顯示任何違反 React 規則的行為。當它這樣做時,這意味著編譯器跳過了優化該組件或 hook。這是完全可以的,編譯器可以恢復并繼續優化代碼庫中的其他組件。

你不必立即修復所有 ESLint 沖突。您可以按照自己的節奏解決它們,以增加要優化的組件和 hook 的數量,但不需要在使用編譯器之前修復所有問題。

將編譯器推出到您的代碼庫

現有項目

編譯器旨在編譯遵循 React 規則的功能組件和 hook。它還可以通過救助 (跳過) 這些組件或 hook 來處理違反這些規則的代碼。然而,由于 JavaScript 的靈活性,編譯器無法捕獲所有可能的違規,并且可能會以漏報進行編譯:也就是說,編譯器可能會意外編譯一個違反 React 規則的組件/鉤子,這可能導致未定義的行為。

因此,要在現有項目中成功采用編譯器,建議先在產品代碼中的小目錄上運行它。您可以通過將編譯器配置為僅在一組特定的目錄上運行來執行此作:

const ReactCompilerConfig = {sources: (filename) => {return filename.indexOf('src/path/to/dir') !== -1;},
};

您對推出編譯器更有信心時,您也可以將覆蓋范圍擴展到其他目錄,并慢慢將其擴展到整個應用程序。

新項目

如果要啟動新項目,則可以在整個代碼庫上啟用編譯器,這是默認行為。

在 React 17 或 18 中使用 React 編譯器

React 編譯器與 React 19 RC 配合得最好。如果您無法升級,您可以安裝額外的軟件包,這將允許編譯后的代碼在 19 之前的版本上運行。但是,請注意,支持的最低版本為 17。react-compiler-runtime

npm install react-compiler-runtime@rc

你還應該將 correct 添加到你的編譯器配置中,其中 是你目標的 React 的主要版本:target target

// babel.config.js
const ReactCompilerConfig = {target: '18' // '17' | '18' | '19'
};module.exports = function () {return {plugins: [['babel-plugin-react-compiler', ReactCompilerConfig],],};
}

在庫上使用編譯器

React Compiler 也可以用于編譯庫。因為 React Compiler 需要在任何代碼轉換之前在原始源代碼上運行,所以應用程序的構建管道不可能編譯它們使用的庫。因此,建議庫維護者使用編譯器獨立編譯和測試他們的庫,并將編譯后的代碼發送到 npm。

由于您的代碼是預編譯的,因此您的庫的用戶不需要啟用編譯器即可從應用于您的庫的自動記憶化中受益。如果你的庫面向尚未在 React 19 上運行的應用程序,請指定最小目標并將 react-compiler-runtime 添加為直接依賴項。運行時包將根據應用程序的版本使用正確的 API 實現,并在必要時對缺少的 API 進行 polyfill 填充。

庫代碼通常需要更復雜的模式和轉義艙口的使用。因此,建議您確保進行足夠的測試,以便識別在庫上使用編譯器可能出現的任何問題。如果你發現任何問題,你可以隨時使用 'use no memo' 指令選擇退出特定的組件或 hook。

與 app 類似,你不需要完全編譯 100% 的組件或 hook 就能看到你的庫里的好處。一個好的起點可能是確定庫中對性能最敏感的部分,并確保它們不會違反 React 規則,你可以用它來識別。eslint-plugin-react-compiler

用法

Babel

npm install babel-plugin-react-compiler@rc

編譯器包括一個 Babel 插件,您可以在構建管道中使用它來運行編譯器。

安裝后,將其添加到你的 Babel 配置中。請注意,編譯器首先在管道中運行至關重要:

// babel.config.js
const ReactCompilerConfig = { /* ... */ };module.exports = function () {return {plugins: [['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!// ...],};
};

babel-plugin-react-compiler應該在其他 Babel 插件之前先運行,因為編譯器需要輸入源信息進行聲音分析。

Vite

如果你使用 Vite,你可以將插件添加到 vite-plugin-react 中:

// vite.config.js
const ReactCompilerConfig = { /* ... */ };export default defineConfig(() => {return {plugins: [react({babel: {plugins: [["babel-plugin-react-compiler", ReactCompilerConfig],],},}),],// ...};
});

Next.js :

參閱 Next.js 文檔

Remix

安裝 ,并向其添加編譯器的 Babel 插件:vite-plugin-babel

npm install vite-plugin-babel
// vite.config.js
import babel from "vite-plugin-babel";const ReactCompilerConfig = { /* ... */ };export default defineConfig({plugins: [remix({ /* ... */}),babel({filter: /\.[jt]sx?$/,babelConfig: {presets: ["@babel/preset-typescript"], // if you use TypeScriptplugins: [["babel-plugin-react-compiler", ReactCompilerConfig],],},}),],
});

Webpack

社區 webpack loader已提供。

故障 排除

要報告問題,請首先在 React Compiler Playground 上創建一個最小重現,并將其包含在你的錯誤報告中。您可以在 facebook/react 存儲庫中打開問題。

你也可以通過申請成為成員在 React 編譯器工作組中提供反饋。有關 加入的更多詳細信息,請參閱 README。

編譯器假定什么?

React 編譯器假定你的代碼:

  1. 是有效的語義 JavaScript。
  2. 測試在訪問可空/可選值和屬性之前是否定義它們(例如,如果使用 TypeScript,則通過啟用 strictNullChecks ),即或使用 optional-chaining 。if (object.nullableProperty) { object.nullableProperty.foo }object.nullableProperty?.foo
  3. React 的規則。

React Compiler 可以靜態驗證 React 的許多規則,并在檢測到錯誤時安全地跳過編譯。要查看錯誤,建議同時安裝 。eslint-plugin-react-compiler。

如何知道我的組件已優化?

React DevTools (v5.0+) 和 React Native DevTools內置了對 React 編譯器的支持,并將在編譯器優化的組件旁邊顯示 “Memo ? ” 徽章。

編譯后某些內容無法正常工作

如果你安裝了 eslint-plugin-react-compiler,編譯器會在你的編輯器中顯示任何違反 React 規則的行為。當它這樣做時,這意味著編譯器跳過了優化該組件或 hook。這是完全可以的,編譯器可以恢復并繼續優化代碼庫中的其他組件。你不必立即修復所有 ESLint 沖突。您可以按照自己的節奏解決這些問題,以增加要優化的組件和 hook 的數量。

然而,由于 JavaScript 的靈活和動態特性,不可能全面檢測所有情況。在這些情況下,可能會出現錯誤和未定義的行為,例如無限循環。

如果你的 app 在編譯后無法正常工作,并且你沒有看到任何 ESLint 錯誤,則編譯器可能錯誤地編譯了你的代碼。為了確認這一點,請嘗試通過 “use no memo” 指令主動選擇退出您認為可能相關的任何組件或 hook,從而使問題消失。

function SuspiciousComponent() {"use no memo"; // opts out this component from being compiled by React Compiler// ...
}

注意
“use no memo”
"use no memo"是一個臨時的轉義艙口,允許你選擇退出 React 編譯器編譯的組件和鉤子。這個指令并不意味著像 use client 那樣長壽。

除非絕對必要,否則不建議使用該指令。一旦你選擇退出一個組件或 hook,它就會永遠選擇退出,直到該指令被刪除。這意味著,即使您修復了代碼,編譯器仍將跳過編譯它,除非您刪除該指令。
#如果你覺得這篇文章對你有幫助,請點贊 👍、收藏 👏 并關注我!👀

當您使錯誤消失時,請確認刪除 opt out 指令會使問題再次出現。然后使用 React Compiler Playground 與React共享錯誤報告(您可以嘗試將其簡化為一個小的復制,或者如果它是開源代碼,您也可以直接粘貼整個源代碼),以便官方識別并幫助解決問題。

如果你覺得這篇文章對你有幫助,請點贊 👍、收藏 👏 并關注我!👀

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82396.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82396.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82396.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mac下通過anaconda安裝Python

本次分享mac下通過anaconda安裝Python、Jupyter Notebook、R。 anaconda安裝 點擊&#x1f449;https://www.anaconda.com/download&#xff0c; 點擊Mac系統安裝包&#xff0c; 選擇Mac芯片&#xff1a;蘋果芯片 or intel芯片&#xff0c; 選擇蘋果芯片圖形界面安裝&#x…

Pandas 技術解析:從數據結構到應用場景的深度探索

序 我最早用Python做大數據項目時&#xff0c;接觸最早的就是Pandas了。覺得對于IT技術人員而言&#xff0c;它是可以屬于多場景的存在&#xff0c;因為它的本身就是數據驅動的技術生態中&#xff0c;對于軟件工程師而言&#xff0c;它是快速構建數據處理管道的基石&#xff1…

【循環神經網絡RNN第一期】循環神經網絡RNN原理概述

目錄 &#x1f9e0; 什么是循環神經網絡&#xff08;RNN&#xff09;&#xff1f;&#x1f501; RNN 的結構圖&#x1f504; RNN 的“記憶”與問題RNN梯度推導 &#x1f9ec; LSTM&#xff1a;解決長期依賴問題&#x1f9f1; LSTM 的核心結構LSTM總結 參考 人類在思考的時候&am…

代碼隨想錄算法訓練營 Day60 圖論Ⅹ Bellmen_ford 系列算法

圖論 題目 94. 城市間貨物運輸 I Bellmen_ford 隊列優化算法 SPFA 大家可以發現 Bellman_ford 算法每次松弛 都是對所有邊進行松弛。 但真正有效的松弛&#xff0c;是基于已經計算過的節點在做的松弛。 本圖中&#xff0c;對所有邊進行松弛&#xff0c;真正有效的松弛&#…

Juce實現Table自定義

Juce實現Table自定義 一.總體展示概及概述 在項目中Juce中TableList往往無法滿足用戶需求&#xff0c;頭部和背景及背景顏色設置以及在Cell中添加自定義按鈕&#xff0c;所以需要自己實現自定義TabelList&#xff0c;該示例是展示實現自定義TableList&#xff0c;實現自定義標…

C++ set數據插入、set數據查找、set數據刪除、set數據統計、set排序規則、代碼練習1、2

set數據插入&#xff0c;代碼見下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…

深度學習賦能圖像識別:技術、應用與展望

論文&#xff1a; 一、引言? 1.1 研究背景與意義? 在當今數字化時代&#xff0c;圖像作為信息的重要載體&#xff0c;廣泛存在于各個領域。圖像識別技術旨在讓計算機理解和識別圖像內容&#xff0c;將圖像中的對象、場景、行為等信息轉化為計算機能夠處理的符號或數據 &am…

深入解析C++引用:從別名機制到函數特性實踐

1.C引用 1.1引用的概念和定義 引用不是新定義?個變量&#xff0c;而是給已存在變量取了?個別名&#xff0c;編譯器不會為引用變量開辟內存空間&#xff0c;它和它引用的變量共用同?塊內存空間。比如四大名著中林沖&#xff0c;他有一個外號叫豹子頭&#xff0c;類比到C里就…

【從0-1的HTML】第1篇:HTML簡介

1 HTML簡介 HTML是用來描述網頁的一種語言,是超文本標記語言的縮寫(Hyper Text Markup Language),不屬于編程語言的范疇&#xff0c;屬于一種標記語言。 標記語言使用一套標記標簽(Markup tag)&#xff0c;又稱為標簽,HTML就是使用標記標簽來描述網頁。 1.2 HTML標簽 1、HTM…

vue+cesium示例:地形開挖(附源碼下載)

基于cesium和vue繪制多邊形實現地形開挖效果&#xff0c;適合學習Cesium與前端框架結合開發3D可視化項目。 demo源碼運行環境以及配置 運行環境&#xff1a;依賴Node安裝環境&#xff0c;demo本地Node版本:推薦v18。 運行工具&#xff1a;vscode或者其他工具。 配置方式&#x…

qwen大模型在進行詞嵌入向量時,針對的詞表中的唯一數字還是其他的?

qwen大模型在進行詞嵌入向量時,針對的詞表中的唯一數字還是其他的? Qwen大模型進行詞嵌入向量時,針對的是詞表中每個 Token 對應的唯一數字(Token ID) ,核心邏輯結合詞表構建、嵌入過程展開 一、Qwen 詞表與 Token ID Qwen 用 BPE 分詞器(基于 tiktoken,以 cl100k 為…

動態規劃-1143.最長公共子序列-力扣(LeetCode)

一、題目解析 對于給定了兩個字符串中&#xff0c;需要找到最長的公共子序列&#xff0c;也就是兩個字符串所共同擁有的子序列。 二、算法原理 1、狀態表示 dp[i][j]&#xff1a;表示s1的[0,i]和s2的[0,j]區間內所有子序列&#xff0c;最長子序列的長度 2、狀態轉移方程 根…

互聯網c++開發崗位偏少,測開怎么樣?

通過這標題&#xff0c;不難看出問這個問題的&#xff0c;就是沒工作過的。如果工作過&#xff0c;那就是不斷往深的鉆研&#xff0c;路越走越窄&#xff0c;找工作一般就是找原來方向的。沒工作過的&#xff0c;那一般就是學生。 學生找什么方向的工作比較好&#xff1f; 學生…

推薦算法八股

跑路了&#xff0c;暑期0offer&#xff0c;華為主管面掛了&#xff0c;真幽默&#xff0c;性格測評就掛了居然給我一路放到主管面&#xff0c;科大迅飛太囂張&#xff0c;直接跟人說后面要面華為&#xff0c;元戎啟行&#xff0c;學了C后python完全忘了怎么寫&#xff0c;挺尷尬…

Spring Boot微服務架構(九):設計哲學是什么?

一、Spring Boot設計哲學是什么&#xff1f; Spring Boot 的設計哲學可以概括為 ??“約定優于配置”?? 和 ??“開箱即用”??&#xff0c;其核心目標是??極大地簡化基于 Spring 框架的生產級應用的初始搭建和開發過程??&#xff0c;讓開發者能夠快速啟動并運行項目…

前端導入Excel表格

前端如何在 Vue 3 中導入 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;&#xff1f; 在日常開發中&#xff0c;我們經常需要處理 Excel 文件&#xff0c;比如導入數據表格、分析數據等。文章將在 Vue 3 中實現導入 .xls 和 .xlsx 格式的文件&#xff0c;并解析其中的數據…

C++和C#界面開發方式的全面對比

文章目錄 C界面開發方式1. **MFC&#xff08;Microsoft Foundation Classes&#xff09;**2. **Qt**3. **WTL&#xff08;Windows Template Library&#xff09;**4. **wxWidgets**5. **DirectUI** C#界面開發方式1. **WPF&#xff08;Windows Presentation Foundation&#xf…

刷leetcode hot100返航必勝版--鏈表6/3

鏈表初始知識 鏈表種類&#xff1a;單鏈表&#xff0c;雙鏈表&#xff0c;循環鏈表 鏈表初始化 struct ListNode{ int val; ListNode* next; ListNode(int x): val&#xff08;x&#xff09;,next(nullptr) {} }; //初始化 ListNode* head new ListNode(5); 刪除節點、添加…

軟考 系統架構設計師系列知識點之雜項集萃(78)

接前一篇文章&#xff1a;軟考 系統架構設計師系列知識點之雜項集萃&#xff08;77&#xff09; 第139題 以下關于軟件測試工具的敘述&#xff0c;錯誤的是&#xff08;&#xff09;。 A. 靜態測試工具可用于對軟件需求、結構設計、詳細設計和代碼進行評審、走查和審查 B. 靜…

【Unity】云渲染

1 前言 最近在搞Unity云渲染的東西&#xff0c;所以研究了下官方提供的云渲染方案Unity Renderstreaming。注&#xff1a;本文使用的Unity渲染管線是URP。 2 文檔 本文也只是介紹基本的使用方法&#xff0c;更詳細內容參閱官方文檔。官方文檔&#xff1a;Unity Renderstreamin…