本文發表於注: 本文為第12屆d2前端技術論壇《打造高可靠與高效能的react同構解決方案》分享內容,已經過資料脫敏處理。
效能是乙個綜合性的問題, 不能簡單地斷言同構應用一定比非同構應用效能好,只能說合適的場景加上合理的運用,同構應用確實能帶來一定的效能提公升, 先來看乙個線上的案例。
通常來說,網路狀況越差,同構的優勢越明顯,下圖是在不同網路狀況下首屏渲染時間的一組對比
除了開源框架,底層方面react16重構了ssr, react-router提供了更加友好的ssr支援等等, 從某種程度上來說,同構也是一種趨勢,至少是方向之一。
同構的出發點不是 「為了做同構,所以做了」, 而是回歸業務,去解決業務場景中seo、首屏效能、使用者體驗 等問題,驅動我們去尋找可用的解決方案。在這樣的場景下,除了同構本身,我們還需要考慮的是:
簡單歸納就是, 我們需要乙個 企業級的同構渲染解決方案。
我們是怎麼做的?
基於 eggjs 加入可拔插的同構能力
這裡不再贅述具體如何實現,有興趣的讀者可以閱讀我們的開源同構框架beidou --
任何一種技術都有其適用場景和侷限性, 同構也不例外,以下試舉一二,以做拋磚引玉.
記憶體洩漏不是同構應用所特有的,理論上所有服務端應用都可能記憶體洩漏,但同構應用是「高危群體」, 具體如何解決請參考本人的《node應用記憶體洩漏分析方**與實戰》, 接下來重點剖析下效能優化。
前面也提到了,同構應用並不一定就比非同構應用效能好,影響效能的因素實在太多了,再來看一組資料
上圖是基於node v8.9.1 和 [email protected], 開4個程序採集到的資料, x軸是最終生成頁面節點數量,y軸紅色的線表示rt(包括渲染時間和網路時間), 綠色的柱子表示qps. 可以看出來:
順帶提一下, 筆者取樣了**首頁 和**某詳情頁以及lazada某詳情頁,頁面節點數分別是2620、2467和3701. 大部分情況下,頁面節點數低於1000, 比如菜鳥物流市場首頁看起來內容不少,其實節點數是775.
那針對3000節點以上的頁面,我們該怎麼做呢?筆者總結了以下策略並重點闡述其中一兩點:
元件級快取
注入快取邏輯, **如下
const reactcompositecomponent = require("react/lib/reactcompositecomponent");
reactcompositecomponent.mixin._mountcomponent = reactcompositecomponent.mixin.mountcomponent;
reactcompositecomponent.mixin.mountcomponent = function(rootid, transaction, context) else
};
lrucachesettings:
上述快取邏輯是基於屬性的,能覆蓋大部分的應用場景,但有乙個要求,屬性值必須可列舉且可選項很少. 請看下面的場景。
**某頁面上有大量的商品,而**的商品又何止百萬,就算某個被快取,下次被命中的可能性依然微乎其微。那如何解決這個問題?聰明的讀者可能已經看出來了,雖然每個商品最終渲染的結果千變萬化,但結構始終是一致的,因此結構是可以快取的。
要實現結構的快取,需要在上述邏輯上額外新增三步。
快取中間結構
生成最終元件
以上就是元件級快取的實現方式, 特別要提醒的是快取是把雙刃劍,運用不當可能會引發記憶體洩漏以及資料的不一致。
筆者拿之前的應用公升級到react16, 對比下3909節點,rt從295ms降到了51ms, qps從9提公升到了44, 提公升非常明顯。
接下來通過乙個例子,展示如何一步步地提公升效能。
**倉庫 -- /
至此,服務端渲染時間已經最初的295.75ms
降低到了2.68ms
,提公升了超過100倍。
其實除了上述應用的策略,還有其它的策略,比如
借用《功夫》中的一句經典台詞天下武功,無堅不破,唯快不破
,同樣的,
隨著時間的推移,上面這些策略策略遲早會被破
,比如react16 ssr重構之後,之前的元件級別快取邏輯不再有效。
另外,可能由於架構設計/技術選型根本就使不上勁,比如react16是今年9月26才正式發版,很多第三方元件還沒來得及公升級,如果應用中有些元件強依賴於react15或者更早的版本,可能根本就沒法利用react16的效能優勢。
那麼有沒有一種萬能的辦法
,能夠做到唯快不破
呢?
答案是: 有的。 只有掌握了方**,才能在不斷變化中,找到適合自己應用的效能優化策略。
具體的方**,請參考本人的另外一篇文章《唯快不破,讓nodejs再快一點》
React 效能優化
避免重複渲染 當乙個元件的props或者state改變時,react通過比較新返回的元素和之前渲染的元素來決定是否有必要更新實際的dom。當他們不相等時,react會更新dom。在一些情況下,你的元件可以通過重寫這個生命週期函式shouldcomponentupdate來提公升速度,它是在重新渲染過...
react 效能優化
在shouldcomponentupdate 方法中判斷props和state是否改變,若未改變則無需渲染。有些情況如父元件的props或state改變了,但是子元件其實未改變,若不判斷的話會導致子元件一起被渲染。shouldcomponentupdate nextprops nextstate r...
React效能優化
一 事件的優化 1 建構函式中宣告 export default mycom extends component render fun 此中方式只會在建構函式中建立一次,效能最好,但無法傳值 2 在元件中宣告 export default mycom extends component fun 該方...