[譯] 高效能 React:3 個新工具加速你的應用

磊仔發表於2019-03-04

通常來說 React 是相當快的,但開發者也很容易犯一些錯誤導致出現效能問題。元件掛載過慢、元件樹過深和一些非必要的渲染週期可以迅速地聯手拉低你的應用速度。

幸運的是有大量的工具,甚至有些是 React 內建的,可以幫助我們檢測效能問題。本文將著重介紹一些加快 React 應用的工具和技術。每一部分都配有一個可互動而且(希望是)有趣的 demo!

工具 #1: 效能時間軸

React 15.4.0 引入了一個新的效能時間軸特性,可以精確展示元件何時掛載、更新和解除安裝。也可以讓你視覺化地觀察元件生命週期相互之間的關係。

注意: 目前,這一特性僅支援 Chrome、Edge 和 IE,因為它呼叫的 User Timing API 還沒有在所有瀏覽器中實現。

如何使用

  1. 開啟你的應用並追加一個引數:react_perf。例如, http://localhost:3000?react_perf
  2. 開啟 Chrome 開發者工具 Performance 欄並點選 Record
  3. 執行你想要分析的操作。
  4. 停止記錄。
  5. 觀察 User Timing 選項下的視覺化檢視。

理解輸出結果

每一個色條顯示的是一個元件做“處理”的時間。由於 JavaScript 是單執行緒的,每當一個元件正在掛載或渲染,它都會霸佔主執行緒,並阻塞其他程式碼執行。

[update] 這樣中括號內的文字描述的是生命週期的哪一個階段正在發生。把時間軸按照步驟分解,你可以看到依據方法的細粒度的計時,比如 [componentDidMount] [componentWillReceiveProps] [ctor] (constructor) 和 [render]

堆疊的色條代表元件樹,雖然在 React 擁有過深的元件樹也比較典型,但如果你想優化一個頻繁掛載的元件,減少巢狀元件的數量也是有幫助的,因為每一層都會增加少量的效能和記憶體消耗。

這裡需要注意的是時間軸中的計時時長是針對 React 的開發環境構建的,會比生產環境慢很多。實際上效能時間軸本身也會拖慢你的應用。雖然這些時長不能代表真正的效能指標,但不同元件間的相對時間是精確的。而且一個元件是否完全被更新不取決於是否是生產環境的構建。

Demo #1

出於樂趣,我故意寫了一個具有嚴重效能問題的 TodoMVC 應用。你可以在這裡嘗試

開啟 Chrome 開發者工具,切換到 “Performance” 欄,點選 Record 開始記錄時間軸。然後在應用中新增一些 TODO,停止記錄,檢查時間軸。看看你能不能找出造成效能問題的元件 :)

Tool #2: why-did-you-update

在 React 中最影響效能的問題之一就是非必要的渲染週期。預設情況下,一旦父元件渲染,React 元件就會跟著重新渲染,即使它們的 props 沒有變化也是如此。

舉個例子,如果我有一個簡單的元件長這樣:

class DumbComponent extends Component {
  render() {
    return <div> {this.props.value} </div>;
  }
}複製程式碼

它的父元件是這樣:

class Parent extends Component {
  render() {
    return <div>
      <DumbComponent value={3} />
    </div>;
  }
}複製程式碼

每當父元件渲染,DumbComponent 就會重新渲染,儘管它的 props 沒有改變。

一般來講,如果 render 執行,並且虛擬 DOM 沒有改變,而且既然 render 應該是個純淨的沒有任何副作用的方法,那麼這就是一個不必要的渲染週期。在一個大型應用中檢測這種事情是非常困難的,但幸運的是有一個工具可以幫得上忙。

使用 why-did-you-update

why-did-you-update 是一個 React 鉤子工具,用來檢測潛在的非必要元件渲染。它會檢測到被呼叫但 props 沒有改變的元件 render

安裝

  1. 使用 npm 安裝: npm i --save-dev why-did-you-update
  2. 在你應用中的任何地方新增下面這個片段:

    import React from 'react'

    if (process.env.NODE_ENV !== 'production') {
    const {whyDidYouUpdate} = require('why-did-you-update')
    whyDidYouUpdate(React)
    }

注意: 這個工具在本地開發環境使用起來非常棒,但是要確保生產環境要禁用掉,因為它會拖慢你的應用。

理解輸出結果

why-did-you-update 在執行時監聽你的應用,並用日誌輸出可能存在非必要更新的元件。它讓你看到一個渲染週期前後的 props 對比,來決定是否可能存在非必要的更新。

Demo #2

為了演示 why-did-you-update,我在 TodoMVC 中安裝了這個庫並放在 Code Sandbox 網站上,這是一個線上的 React 練習場。 開啟瀏覽器控制檯,並新增一些 TODO 來檢視輸出。

這裡檢視 demo

注意這個應用中很少的元件存在非必要渲染。嘗試執行上述的技術來避免非必要渲染,如果操作正確,why-did-you-update 不會在控制檯輸出任何內容。

Tool #3: React Developer Tools

React Developer Tools 這個 Chrome 擴充套件有一個內建特性用來視覺化元件更新。這有助於防止非必要的渲染週期。使用它,首先要確保在這裡安裝了這個擴充套件

然後點選 Chrome 開發者工具中的 “React” 選項卡開啟擴充套件並勾選“Highlight Updates”。

然後簡單操作你的應用。和不同的元件互動並觀察 DevTools 施展它的魔法。

理解輸出結果

React Developer Tools 在給定的時間點高亮正在重新渲染的元件。根據更新的頻率,使用不同的顏色。藍色顯示罕見更新,經過綠色、黃色的過渡,一直到紅色用來顯示更新頻繁的元件。

看到黃色或紅色並不必要覺得一定是壞事。它可能發生在調整一個滑塊或頻繁觸發更新的其他 UI 元素,這屬於意料之中。但如果當你點選一個簡單的按鈕並且看到了紅色這可能就意味著事情不對了。這個工具的目的就是識破正在發生非必要更新的元件。作為應用的開發者,你應該對給定時間內哪個元件應該被更新有一個大體的概念。

Demo #3

為了演示高亮,我故意讓 TodoMVC 應用更新一些非必要的元件。

這裡檢視 demo

開啟上面的連結,然後開啟 React Developer Tools 並啟用更新高亮。當你在上面的文字輸入框中輸入內容時,你將看到所有的 TODO 非必要地高亮。你輸入得越快,你會看到顏色變化指示更新越來越頻繁。

修復非必要渲染

一旦你已經確定應用中非必要重新渲染的元件,有幾種簡單的方法來修復。

使用 PureComponent

在上面的例子中,DumbComponent 是隻接收屬性的純函式。這樣,元件就只有當它的 props 變化的時候才重新渲染。React 有一個特殊的內建元件型別叫做 PureComponent,就是適用這種情況的用例。

與繼承自 React.Component 相反,像這樣使用 React.PureComponent:

class DumbComponent extends PureComponent {
  render() {
    return <div> {this.props.value} </div>;
  }
}複製程式碼

那麼只有當這個元件的 props 實際發生變化時它才會被重新渲染了。就是這樣!

注意 PureComponent 對 props 做了一個淺對比,因此如果你使用複雜的資料結構,它可能會錯失一些屬性變化而不會更新你的元件。

呼叫 shouldComponentUpdate

shouldComponentUpdate 是一個在 render 之前 propsstate 發生改變時被呼叫的元件方法。如果 shouldComponentUpdate 返回 true,render 將會被呼叫,如果返回 false 什麼也不會發生。

通過執行這個方法,你可以命令 React 在 props 沒有發生改變的時候避免給定元件的重新渲染。

例如,我們可以在上文中的 DumbComponent 中這樣呼叫 shouldComponentUpdate

class DumbComponent extends Component {
  shouldComponentUpdate(nextProps) {
    if (this.props.value !== nextProps.value) {
      return true;
    } else {
      return false;
    }
  }

render() {
    return <div>foo</div>;
  }
}複製程式碼

在生產環境中除錯效能問題

React Developer Tools 只能在你自己的機器上執行的應用中使用。如果您有興趣瞭解使用者在生產中看到的效能問題,試試 LogRocket

LogRocket 就像是 web 應用的 DVR,會記錄發生在你的站點上的所有的一切。你可以重現帶有 bug 或效能問題的會話來快速瞭解問題的根源,而不用猜測問題發生的原因。

LogRocket 工具為你的應用記錄效能資料、Redux actions/state、日誌、帶有請求頭和請求體的網路請求和響應以及瀏覽器的後設資料。它也能記錄頁面上的 HTML 和 CSS,甚至可以為最複雜的單頁面應用重新建立完美畫素的視訊。

LogRocket | 為 JavaScript 應用而生的日誌記錄和會話回放工具
LogRocket 幫助你瞭解用影響你使用者的問題,這樣你就可以回過頭來構建偉大的軟體了。
logrocket.com


感謝閱讀,希望這些工具和技術能在你的下一個 React 專案中幫到你!


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃

相關文章