光速React–Vixlet
自此我們的web-app中,包含有幾百甚至上千的媒體,文本,視頻以及鏈接等內容,我們花了很長的時間去摸索關於react構建的方式,這裡我們將分享一些踩過的經驗。
聲明: 講解的這些經驗和方法,已經能夠很好的滿足我們特殊應用的需求,然而,如果是整體開發的話,將你的應用和團隊考慮其中至關重要,React的速度是相當快的,所以你可能沒有必要很精確的了解到我們的使用場景,但是,我們希望你能發現一些發送的有益的信息。
基本原理
GIF/476K
向更大的世界邁出一步.
The render() 函數
作為一個通用原則,盡量在render函數裡面少做事,如果實在很有必要運行一些複雜的操作和計算,也許可以考慮將他們移到memoized函數裡面, 這樣得到的結果能夠被緩存.了解Lodash.memoize關於 memoization函數的模型.
相反地,去避免更改巨大的,輕易計算的值在組件中的狀態是很重要的。例如,如果props參數同時包含 和 ,那麼就沒必要在state狀態裡面包含 ,因為它很容易從props屬性裡面獲得。 如果一個值能以一種很有效的方式通過props獲得,通過使用通用的字元串連接,或者基本的的演算法操作,那麼我們就沒必要更改狀態來獲取該值了。
Prop 和 Reconciliation
這是很重要的,記住React觸發時,是會重新渲染的,其prop值(或者state狀態)跟之前的值是不相等的。它包含了在嵌套組件,且其props和state包含對象或者數組之內的任何變化,記住這一點,這是很重要的情況,就是可能不經意的render循環,去創造prop或者state的值,就可能引起巨大的性能衝擊。
例如:函數綁定問題
例如:對象或者數組的字面值
例如_: 注意fallback返回的值
儘可能的保證Props(和state)最小
一般來講,props是在被需要的情況下,才會傳遞給一個組件,通過一個大且複雜的對象,或者很多個單獨的props傳遞給組件,僅僅只是為了給其子組件傳遞值,但這會引起不必要的組件渲染(同時增加了開發的複雜性).
在我們Vixlet這邊,我們使用Redux作為state的容器,因此在我們的這種情況,大部分是從react-redux中使用connect()函數,根據組件中的每一個等級去直接獲取需要的數據。connect()函數是非常高性能並且佔用的開銷非常小。
組件方法
自從給每一個組件實列賦予了組件的方法,如果可以的,你要麼使用純粹的來自helper/util模板中的函數,要麼使用靜態類方法,這裡有一個特別值得注意的地方,就是當有很大數字的組件在app裡面進行渲染的時候。
高級
GIF/1304K
讀完我的觀點,jank變得邪惡了!
shouldComponentUpdate()
React生命周期中包含一個的方法 .這個方法可以告訴React,組件是否應該被渲染或者不依賴當前或者下一個props/state的值。
然而使用這個方法有個問題,那就是開發者必須仔細考慮每一種重新渲染髮生的條件。這就使邏輯變得很複雜,通常來說,這太痛苦了,如果你真的需要它,那你就使用 方法,但是對於很多的情況,一般都有更好的選擇。
React.PureComponent
React v15版本開始,其包含了 PureComponent類,可以用來建立組件。 基本實現了它自己的 方法,並且能夠自動判斷出當前以及下一個props/state組件之間的比較。如果想看更多的信息,請至Stack Overflow:
在幾乎所有的情況中, 無疑是比 更好的選擇.當創建一個新的組件時候,試著將其建立為一個純粹的組件先,並且將組件功能引入,使用 .
更多信息: 官方React文檔
組件運行分析 (in Chrome)
在最新Chrome版本,新增了一個建立時間表功能的工具,它可以將React組件渲染詳細的信息,以及所花的時間顯示出來。使用該功能只需要添加 放在你想測試的url的後面即可。React渲染的時間列表數據,將會在用戶時間部分之下顯示。
更多信息:Profiling Components with Chrome Timeline官方React文檔
有用的Utility:why-did-you-update
這是一個很好的NPM包,當沒有必要重新渲染組件的時候,它能進行補丁,在console裡面列印出來通知。
注: 這個模塊能夠使用過濾器進行初始化,去匹配特殊的你想要的組件,否則你的所有console出來的東西,都會被識別為垃圾信息,或者你的瀏覽器可能會崩潰,至why-did-you-update docs獲取更多細節信息。
常見的性能陷阱
GIF/808K
setTimeout() and setInterval()
使用 or 在一個 React組件之中,需要極其的小心。這裡幾乎是更好的選擇去使用 resize 和 scroll 事件 (注: 見下一章節需要注意的事項).
如果你需要使用 or , 你必須遵循下面幾個禁令
極其短時間內持續發生不要使用
短時間內持續發生是沒有必要使用的,特別是小於100ms的,如果更短的時間內,真的需要,也許你可以使用 來代替.
參考這些取消/清除函數
and 都返回一個唯一的標識符,對於延遲函數,如果有必要可以對其進行取消操作。自從這些函數在全局範圍內運行,他們不需要關心你的組件是否已經不在,它會直接導致報錯或者停止運行。+
注: 這是真的對於 來說
如果你不希望引入一個依賴,並且想要用你自己的方案去解決這個問題,下面這些可能對你的會有幫助:
如果你在使用requestAnimationFrame()來控制動畫循環,你可以使用很小的通知來進行類似的處理。
去抖和防流事件
一定程度上來說,正常的事件是極其迅速的,像"scroll","resize".這是很明智的,去抖事件,特別是如果這些事件被解決的話,遠遠比那些極其基本的功能執行的好。
Lodash有 方法. 這裡依然是一個獨立的 NPM包
"但是我真的需要scroll/resize/無論什麼事件立即響應"
我曾經發現了一種模式可以以一種高性能的方式來解決這類事件響應問題,那就是使用 來監聽事件開始和結束的時間,然後, 函數通過使用 選項來設置為 (這就意味著函數僅僅在節流函數結束之後才結束)來阻止監聽這個值,看下面的例子
密集的CPU任務導致線程阻塞
毫無疑問,很多任務一起將會加強CPU的損耗,因此引起主要的渲染阻塞,一些例子包括非常複雜的數學計算,通過一個很大的數組進行迭代,通過使用 api來進行渲染/覆寫. 加密或者解密圖像數據從`` object中.
如果在所有的情節當中,也許使用web搬運工,將其一些功能性的東西搬移到另外一個線程中會更好,因此,我們的主要渲染進程中能夠順利的進行。
閱讀這些
MDN 文章:Using Web Workers
MDN 文檔:Worker API
結尾
我們希望你已經發現上面這些有用的建議和信息。最後說一句,如果沒有我們的Vixlet團隊,上面這些技巧和提示方法是不可能被搜索出來,並且很好的運行的,他們真的是我工作以來,有幸接觸到的一群非常優秀的團隊夥伴。
在React之外進行升華,持續學習和練習,希望和你一起進步!
謝謝Matt Lubner
※上海共享雨傘上線當天就不翼而飛
※陽光沙灘上的小米手機 6 拍妹兒體驗
※13種應用推廣方法與渠道
※手把手教你用 TensorFlow 實現文本分類
※專訪小米林斌:第100家小米之家開業,今年總銷售額突破1000億不困難
TAG:推酷 |
※Flutter vs React Native
※React, Redux 和 React Router 速查表
※Matthew M.Williams x Nike 更多產品細節曝光,Nike Epic React 熒光配色釋出
※React Native BackHandler exitApp 源碼分析
※React Native 與 Flutter 的跨平台之戰
※堪比Be True,炫酷Nike Epic React Flyknit 「Belgium」曝光
※Matthew M.Williams x Nike 更多產品細節曝光,Nike Epic React 熒光配色釋出丨今日資訊
※Paris Saint-Germain x Nike 全新聯名 Epic React Flyknit 2 系列突擊上架
※Nike React Element 87 釋出全新「Metallic Gold」配色
※Nike React Element 87「Off-White」概念設計曝光
※Nike React Element 87 全新「Light Orewood」配色
※Nike Epic React Flyknit 全新「Triple White」配色上架
※React+Air Presto!全新 Presto React 明年登場!
※全新Betrue配色!Nike Epic React Flyknit
※Nike React Element 87 再迎來兩新配色「Red Orbit」及「Orange Peel」
※Nike React Element 87
※預覽 Nike React Flyknit 「Belgium」,VaporMax Moc 2 推出全新橄欖綠配色
※React + Air Presto!全新 Presto React 明年登場!
※Nike React Element 55
※Nike Epic React Flyknit跑鞋