當前位置: 妍妍網 > 碼農

React 全新編譯器太好用了!

2024-05-11碼農

未經授權,禁止轉載,轉載請註明出處!

React 18 已經釋出兩年多了,現在終於要迎來 React 19 了。這個版本將引入期待已久的全新 React 編譯器!它透過自動化最佳化來簡化前端開發流程,減少手動進行記憶化最佳化的需求。本文就來看看 React 編譯器是什麽?它是如何工作的?又帶來了哪些好處?

React 19 新特性

React 19 不僅是向前邁進的一步,而且想要改變開發人員在 React 中構建套用的方式。React 19 計劃引入的一些最令人興奮的特性包括:

  • 伺服端元件 :透過伺服端元件,React 19 能夠實作更快的頁面載入速度和更好的 SEO 效果。這意味著在將頁面交付給使用者之前,伺服器會預先處理元件,從而提升使用者體驗和搜尋引擎可見性。

  • Actions :React 19 引入了 Actions,這是一個全新的機制,用於簡化網頁內數據和互動的管理。透過 Actions,開發人員可以更方便地透過表單更新頁面資訊,減少復雜性並最佳化使用者體驗。

  • 最佳化的資源載入 :React 19 在資源載入方面進行了最佳化,允許在後台載入站點資源,以實作更平滑的頁面過渡。這意味著使用者可以在瀏覽當前頁面時,提前載入下一頁所需的圖片和其他檔,從而減少頁面切換時的等待時間。

  • 文件後設資料 :React 19 引入了一個新的 <DocumentHead > 元件,用於簡化 SEO 管理。透過該元件,開發人員可以更方便地向頁面添加標題和元標簽,提高搜尋引擎最佳化效果,而無需進行重復的編碼工作。

  • Web Components :React 19 改善了與 Web Components 標準的相容性,使開發人員能夠更輕松地使用 Web Components 構建靈活、相容的 Web 套用。

  • React 編譯器

    React 編譯器一項自動最佳化工具,旨在透過先進的編譯技術減少不必要的重新渲染,提高 React 套用的效能。在深入探究 React 編譯器的工作原理之前,我們先回顧一下 React 的核心思維模型。

    React 心智模型

    React的核心是一個 聲明式 基於元件 的心智模型。在前端開發中,聲明式編程意味著描述 UI 的期望最終狀態,而無需透過 DOM 操作來指定達到該狀態的每一步。同時,基於元件的方法將 UI 元素分解為可重用、簡潔、自包含的構建塊,促進了模組化並簡化了維護。

    為了有效地辨識需要更新的特定 DOM 元素,React使用了一個稱為虛擬 DOM 的記憶體中UI表示。當套用狀態發生變化時,React會將虛擬DOM與真實DOM進行比較,辨識出所需的最小更改集,並精確地更新真實DOM。

    簡而言之,React的心智模型是:每當套用狀態發生變化時,React就會重新渲染。然而,有時React可能會過於「反應靈敏」,導致不必要的重新渲染,從而降低套用的效能。

    重新渲染的困境

    React 對套用狀態變化的快速響應能力是一把雙刃劍。一方面,由於其聲明式方法,它簡化了前端開發。另一方面,它可能導致 UI 中元件對狀態變化的過度重新渲染。

    當處理如物件和陣列這樣的 JavaScript 數據結構時,重新渲染問題尤為常見。問題在於,JavaScript中沒有一種計算效率高的方法來比較兩個物件或陣列是否相等(即具有相同的鍵和值)。

    考慮以下場景:有一個React元件,它在每次渲染時都會生成一個新的物件或陣列,如下所示:

    import React from"react";
    constAlphabetList=()=>{
    const alphabet =Array.from({length:26},(_, i)=>String.fromCharCode(65+ i));
    return(
    <div>
    <h2>Alphabet List</h2>
    <ul>
    {alphabet.map((letter, index)=>(
    <li key={index}>{letter}</li>
    ))}
    </ul>
    </div>
    );
    };
    exportdefault AlphabetList;

    盡管React元件在每次渲染時可能生成內容相同的本地陣列,但React無法直接辨識出這一點,因此可能會不必要地觸發依賴於該陣列中值的元件及其巢狀DOM元素的重新渲染,即使 UI 實際上沒有變化。這種不受控制的重新渲染會很快導致效能下降,影響使用者體驗。

    為了最佳化這種情況並減少不必要的重新渲染,React 開發人員可以利用記憶化技術。記憶化允許緩存基於特定輸入的計算結果或元件輸出,並在輸入未變時直接復用這些結果。這種方法能夠顯著減少元件的重新渲染次數,提高 React 套用的整體效能和效率。

    React 18 提供了以下記憶化工具來幫助我們實作這一目標:

  • React.memo() :一個高階元件,允許基於props的淺比較來避免元件的重新渲染,只要 props 沒有發生變化。

  • useMemo() :用於在元件重新渲染之間緩存計算的結果。只有當依賴項之一發生變化時, useMemo() 才會重新計算並返回新的結果。

  • useCallback() :用於緩存函式的定義,確保在依賴項未變時不會重新建立函式。

  • 透過使用 useMemo() Hook,可以最佳化 <AlphabetList> 元件,避免在其依賴的數據(如陣列)未發生變化時進行不必要的重新渲染。這種方法能夠顯著提高元件的效能,確保 UI 的流暢性和響應性。

    import React,{ useMemo }from"react";
    constAlphabetList=()=>{
    const alphabet =useMemo(()=>{
    returnArray.from({length:26},(_, i)=>String.fromCharCode(65+ i));
    },[]);
    return(
    <div>
    <h2>Alphabet List</h2>
    <ul>
    {alphabet.map((letter, index)=>(
    <li key={index}>{letter}</li>
    ))}
    </ul>
    </div>
    );
    };
    exportdefault AlphabetList;

    React 的記憶化工具確實在提升效能上起到了關鍵作用,但它們確實增加了開發者的工作量和程式碼復雜度,因為它要求開發者不僅描述 UI 的狀態,還需顯式管理渲染的最佳化。這在一定程度上違背了 React 強調的聲明式編程哲學。

    為了減輕開發者的負擔,理想的解決方案是一個智慧的編譯器或工具鏈,它能夠自動分析 React 元件的依賴關系,並生成最佳化的程式碼。這樣的工具能夠確保元件僅在狀態值發生實質性變化時重新渲染,從而在不犧牲效能的前提下,保持程式碼的簡潔性和可維護性。

    React 編譯器是什麽?

    React 編譯器,亦名React Forget,是一款針對 React 的最佳化編譯器。它目前已在 Instagram 的網頁門戶中投入生產使用,並計劃在首次開源釋出前,擴充套件至 Meta 旗下的其他套用。

    最初,React 編譯器旨在透過自動生成類似於 memo useMemo useCallback 的呼叫,來強化React的核心編程模型,進而降低重新渲染的開銷。隨著時間的推移,該計畫已從「自動記憶化編譯器」演進為更為先進的「自動響應性編譯器」。

    React Forget 的核心目標,是確保 React 套用能夠預設擁有合理的響應性。這意味著套用僅在狀態值發生實質性變化時才會觸發重新渲染。傳統的 React 在物件標識改變時會重新渲染元件,而 React Forget 則透過智慧判斷,僅在物件的語意內容變化時觸發重新渲染,同時避免了深度比較帶來的效能損耗。從技術實作來看,React 編譯器采用了自動記憶化技術。但開發團隊認為,響應性框架是理解其工作原理的更全面視角。

    盡管 JavaScript 的動態特性和寬松規則使其最佳化變得復雜,但 React 編譯器透過模擬JavaScript和React的規則,確保了程式碼編譯的安全性和效率。這些規則在限制開發人員操作的同時,也為編譯器執行最佳化提供了安全的操作空間。

    React 編譯器好處

    React 編譯器的引入帶來了顯著的益處:

  • 簡化記憶化管理 :開發者無需手動編寫和維護復雜的記憶化策略,從而降低了程式碼的復雜性,減少了出錯的風險,並極大簡化了開發流程。

  • 提升開發者體驗 :開發者能夠更專註於核心功能的構建,無需分心於繁瑣的效能最佳化工作。不僅提高了生產力,還讓他們能更充分地利用React的聲明式編程優勢。

  • 加速React套用效能 :React 編譯器智慧地決定何時渲染元件,有效減少了不必要的計算和資源消耗。這使得使用者介面更加流暢和響應迅速,為使用者帶來了更好的體驗,並顯著提升了整體套用的效能。

  • 盡管這些改變令人充滿期待,但我們仍需觀察 React 編譯器在實際程式碼開發中的具體效果。為了確保編譯器能夠高效執行,開發者需要確保他們的程式碼嚴格遵循 React 的規則。因此,官方團隊強烈推薦使用 ESLint 等工具來準備和檢查程式碼,以確保其相容性並充分利用 React 編譯器的潛力。

    React 的規則

    React 設定了一套嚴格的規範,以確保Web套用的高品質。開發者需遵循這些原則,它們同樣是 React 編譯器背後的基石。

    以下是React的幾個核心規則:

  • 冪等性元件 :React元件在接收到相同的輸入(包括 props state context )時,應始終產生一致的輸出。

  • 副作用外部化 :副作用操作(如數據獲取、訂閱或DOM更新)不應嵌入在元件的渲染流程中。它們應被放置在如 useEffect 等生命周期 Hook 中執行。

  • 不可變props與state :React元件中的 props state 應被視為不可變。直接修改它們可能導致錯誤和不可預測的行為。

  • Hooks參數與返回值的不變性 :一旦值被傳遞給 React Hooks,它們應保持不變。Hooks依賴其參數和返回值的穩定性來確保元件行為的一致性和可預測性。

  • 不可變JSX值 :在 JSX 渲染後,不應修改其中使用的值。任何必要的修改應在JSX建立之前進行,以確保渲染結果的穩定性。

  • 元件函式的使用限制 :React元件應透過JSX使用,而非直接作為普通函式呼叫。

  • Hooks的正確使用 :React Hooks(如 useState useEffect )應僅在函陣列件內部使用。將它們作為普通值傳遞可能會導致不符合預期的行為並違反Hooks的使用規則。從常規的JavaScript函式中呼叫hooks可能會導致錯誤並違反hooks的規則。

  • 只在頂層呼叫hooks :React hooks 應該始終在函陣列件的頂層呼叫,即在任何條件語句或迴圈之前。這確保了hooks在每次渲染時都以相同的順序被呼叫,並保持其預期的行為。