AD

2017年8月20日星期日

高性能 React: 3 個提升 APP 速度的新工具

點擊圖片報名參加廣州&珠海源創會


React 已經比較快了,但使用時仍很容易犯些小錯誤,導致其性能下降。組件掛載慢,組件樹層級過深以及沒必要的循環渲染都會讓app感覺很慢。

幸虧有很多工具(有些甚至內置在 React 中)能幫助診斷性能問題。在這篇文章中,我將告訴你快速生成 React 應用程序的工具和技術。每個部分會有一個互動以及(希望是)有趣的演示!


工具1:The Performance Timeline



React 15.4.0 介紹了一種新的性能 timeline 特性可以讓你看到組件安裝、更新和卸載的時間,你還可以看到相關可視化組件的生命周期。

注:現在,該功能隻適用於Chrome,Edge 和 IE,因為它實用的 User Timing API 尚未在所有瀏覽器上實現。

如何運行:

  1. 打開你的 app 並附加查詢參數: react_perf。例如,http://localhost:3000?react_perf

  2. 打開 Chrome DevTools 的 Performance,點擊 Record.

  3. 執行要分析的操作。

  4. 停止記錄。

  5. 檢查  User Timing.

理解輸出的內容

每個顏色欄顯示一個組件"工作"的時間。因為JavaScript是單線程的,當一個組件安裝或渲染,都會占用主線程並防止其他代碼運行。

括號內是 [update]  描述的是組件生命周期的哪一部分正在執行。timeline會把每個步驟分解,所以你可以區分出諸如[componentDidMount][componentWillReceiveProps][ctor](constructor) 和[render]的細微的時間差。

堆疊的條表示組件樹。雖然在 React 中有相當深的組件樹是典型的,但是如果您正在優化頻繁安裝的組件,它可以幫助減少包裝器組件的數量,因為每個組件都有增加一點性能和內存的損耗。

這裏需要注意的一點是,timeline中的數值是用於React開發構建的,所以相對於生產會慢許多。事實上,使用timeline也會使你的app變慢。雖然這些數值並不代表真實環境的性能,但是不同組件的相對時間是精確的。而且,組件是否更新並不取決於生產環境。

這裏需要注意的一點是,timeline中的數值是用於React開發構建的,所以用於實際生產時會感覺比較慢。事實上,使用 timeline 也會使你的 app 變慢。雖然這些數值並不代表真實環境的性能,但是不同組件的相對時間是精確的。另外,組件是否更新並不取決於生產環境。

Demo #1

為了好玩,我在 todomvc APP 增加了一些嚴重的性能問題。你可以在 https://perf-demo.firebaseapp.com/?react_perf 試試。

要查看 timeline,打開 Chrome 開發工具,轉到"Performance"選項,然後單擊"Record"。再在App裏添加一些 TODOs ,停止記錄並查看timeline。你可以看看到底是哪些組件引起了性能問題 :)


工具 2: why-did-you-update


影響 React 中性能的最常見問題之一是不必要的渲染循環。默認情況下,React 組件將在父類渲染時重新渲染,即使他們的 props 沒有改變。

例如,如果我有一個這樣的簡單組件:

有一個這樣的父類組件:

無論何時父組件被渲染時,DumbComponent將被重新渲染,盡管其props並沒有改變。

通常,如果渲染執行完成,並且虛擬DOM並沒有改動,那麼它是一個無用的渲染循環,因為渲染方法應該是純的,而且沒有任何副作用的。在一個大規模的React應用程序中,檢測發生這種情況的發生的位置可能很棘手,但幸運的是,我們有一個可以幫助檢測的工具!

使用 why-did-you-update

why-did-you-update 是一個掛鉤到 React 檢測潛在的不必要的組件渲染的庫。即使props 沒有改變,當一個組件的渲染方法被調用時它也會進行檢測。

安裝程序:

  • npm 安裝:npm i --save-dev why-did-you-update

  • 在應用程序的任何地方添加此代碼:


注:該工具用於本地開發很好,但要確保生產環境下被禁用,因為它會讓你的應用變慢。


理解輸出結果

what-did-you-update用於監測你的應用程序,記錄其運行情況和可能出現的不必要地組件變動。它可以讓你在渲染循環之前和之後看到其屬性以確定該過程是否是不必要的。

Demo #2

為了說明why-did-you-update的原理, 我將該庫安裝在Code Sandbox中的TodoMVC應用程序上,這是一個在線React遊戲機。打開瀏覽器控製台並添加一些TODOs,查看輸出。

演示地址:https://codesandbox.io/s/xGJP4QExn

請注意,應用程序中有幾個組件是沒有必要渲染的。嚐試使用上述技術來預防不必要的渲染。如果正確地完成,那麼在控製台中應該沒有任何why-did-you-update的輸出。


工具 3: React Developer Tools


React Developer Tools Chrome Chrome擴展有一個內置的可視化組件更新功能。這有助於檢測不必要的 render 周期。要使用它,首先要在這裏安裝擴展。

然後,打開擴展通過點擊"React"選項卡中DevTools並檢查"高亮更新(Highlight Updates)"。

然後,簡單地使用你的應用程序。使組件交互,看 DevTools發揮它的魔力。

理解輸出內容

 React Developer Tools 高亮顯示在給定時間內重複渲染的組件。使用藍色、綠色、黃色和紅色表示更新的頻率。

看到黃色或紅色的不一定是壞事。當調整 slider 或 UI 元素頻繁觸發更新時就會出現這種情況。但是如果你點擊一個簡單的按鈕,看到紅色 —— 那可能就是什麼東西出了問題。該工具的目的是發現更新不必要的組件。作為應用程序開發人員,您應該有一個大致的概念,在給定的時間內哪些組件應該更新。

demo #3

為了演示組件高亮,我在 TodoMVC 應用裏更新了一些不必要的組件。

演示地址:https://highlight-demo.firebaseapp.com/

打開上麵的鏈接,然後打開 React Developer Tools 並啟用更新高亮。當您鍵入的文本輸入頭部時就會看到所有TODOs不必要的高亮。當你輸入加快的時候,你會看到顏色的變化得更頻繁。


修複不必要的渲染問題

一旦定位到了應用中的不必要重繪的組件,可以用上這些簡單的修複方法。

使用 purecomponent

在上麵的例子中, dumbcomponent 是其 props 的純函數。也就是說,組件隻需要在 props改變時重新渲染。React 有一個特殊類型的內置組件叫 PureComponent ,說的就是這種使用案例。

從React.PureComponent繼承而不是從React.Component.


然後,組件隻在props發生變化時才重新渲染。就是這麼回事!

注意, purecomponent 隻對 props 做簡單對比,所以如果你使用的是複雜的數據結構,可能會導致錯過一些 prop 的變化而使你的組件得不到更新。

實現 shouldComponentUpdate

shouldComponentUpdate 是一個組件方法,當 props 或 state 改變時,執行render之前就會被調用。如果 shouldcomponentupdate 返回true,render 將被調用,如果它返回false,則什麼也不會發生。

這種方法可以通過判斷它的 props 有沒有改變讓 React 避免重新渲染給定的組件。

例如,在上述例子中的 dumb component 實現shouldComponentUpdate



調試中的性能問題

如果您在自己的機器上運行應用程序,則React開發工具僅僅隻是工作。如果你想在了解用戶感興趣的性能問題,試一下 LogRocket。

LogRocket  就像DVR 之於 Web應用程序,書麵記錄一切發生在你的網站上的情況。建議不要猜測問題發生的原因,而是通過重現 bug 或性能問題以快速了解問題的根本原因。

LogRocket 儀器記錄 app 的性能數據,Redux 行為/狀態、日誌、錯誤、網絡請求/響應信息頭+信息主體,和瀏覽器元數據。它還記錄頁麵上的HTML和CSS,重新生成甚至是最複雜的單頁應用程序的超高清視頻。

LogRocket | Logging and Session Replay for JavaScript Apps(https://logrocket.com/)


更多幹貨請前往公眾號菜單欄"戳我"->"幹貨分享"查看。




推薦閱讀

趕超 Java 和 PHP,Python 躍升為編程語言第一名

Vim 愛好者看過來,12 個實用的 Vim 使用技巧

Spring 思維導圖,讓 Spring 不再難懂(mvc篇)

2017 開發者生態報告:Java 最火,Go 最有前途

點擊"閱讀原文"查看更多精彩內容

相關文章
"在一起"後絕不是隻能進不能退2017年07月27日
【教程】如何正確使用和維護電池?手機、相機、筆記本通用2017年07月27日
孫正義最新預言:巨變即將到來,感覺睡覺都是浪費時間2017年07月27日
【CHRC分享活動】20170802-北京-管理培訓生招募與培養論壇2017年07月27日
沈從文:李白的胡子應該是翹翹的!2017年07月27日
國際奧賽再現黑馬,不過我更關心韓國數學課和中國到底有何不同?2017年07月27日
蒙牛、旺旺、可口可樂集團要做同一款產品!到底誰能贏?2017年07月27日
"我愛生活,我愛加班"2017年07月27日
好久好久沒看過這麼好的懸疑片了2017年07月27日
重回侏羅紀,你能跑贏霸王龍嗎?2017年07月27日

没有评论:

发表评论