使用Performance對頁面進行分析優化(實戰篇)

這篇文章將介紹下實際使用performance對頁面進行優化的過程。總的來講,chrome performance工具讓咱們更方便的發如今代碼運行過程當中的問題在哪裏,便於對一些可能注意不到的問題進行定位、分析和優化。原文首發於我的博客react

渲染優化

首先,咱們對進入整個詳情頁進行分析,整個頁面的結構大體以下,主要包含三個部分:基本信息,可視化圖和時間軸。時間軸內部包含時間軸的詳情信息,包括表格和幾種類型的可視化圖等,內部比較重。如圖所示:git

圖片描述

咱們點擊錄製,查看進入頁面的性能圖:github

優化點1

能夠看到,渲染當前頁面的耗時將近1.2s,咱們看看究竟是哪裏出現了問題。對渲染部分進行放大,咱們發如今渲染時間軸的過程當中,大部分時間耗費在了每一個時間節點詳情內容的展現上面,可是默認狀態下,他們是進行隱藏的。也就是說,咱們進行了N個節點的沒必要要的渲染,只需把他們幹掉就行了。chrome

圖片描述

查看代碼,發現是如下位置致使的,咱們進行了一個展開盒子的封裝,相似這樣:緩存

<Box data={data} border collapse loading={loading}>
  <AlertDetail />
</Box>

在非展開狀態下,咱們依然對內容進行了渲染,只是使用樣式進行了隱藏,可是這樣React仍然會進行虛擬dom的渲染和計算,在這裏咱們對其進行改造,讓其只在展開時進行渲染,並儘可能緩存渲染的結果。修改完成後,咱們會發現,Scripting由以前的880+ms變成了670ms減小了200ms左右:app

圖片描述

優化點2

咱們繼續看,會發現頁面初始化時,詳情部分會有大量的Evaluate Script耗時,主要是耗費在告警詳情右側的分類及各分類下的可視圖及詳情引發的。dom

clipboard.png

咱們可能會想,這裏在初始化時並無進行渲染,爲何仍然會耗費時長進行計算呢?繼續追查我發現緣由在這裏:tcp

clipboard.png

在整個詳情組件中,咱們對包括http,tcp等全部類型的組件進行了引用,而後根據其類型進行組件的匹配,在各個組件中可能包含了每一個類型對應的定義、分類和計算等等等等,不只增長了加載時間,更延長了初始化時間,顯然咱們這麼作是不對的。工具

在此,咱們可使用懶加載方式對其進行優化,僅展現其對應類型的圖,避免了沒必要要的資源浪費和計算時間。性能

clipboard.png

修改以後,咱們再次進行性能測試,發如今進入頁面時,詳情組件的耗費時長由260ms變爲不到2ms:

clipboard.png

而Scripting由以前的670+ms變成了415ms減小了250ms左右:

clipboard.png

至此,進入頁面的耗時已由最開始的1.2s左右變成了如今的0.7s左右。

更新優化

咱們在點擊時間軸查看詳情時,會進行幾個操做。關閉其餘已開啓的詳情內容,展開當前詳情內容,根據當前的類型進行對應類型的詳情內容展現,上邊已經提到過。這個過程會涉及到React的update操做,咱們來對這個過程進行一下優化。

優化點1

首先咱們點擊錄製按鈕,而後點擊展開,並對其進行錄製。咱們會發現如下的結果:

clipboard.png

點擊展開按鈕,Timeline組件進行了屢次重複渲染,顯然這是不該該的,咱們來看下是哪裏致使的。咱們看到整個時間軸組件中,有這樣一段代碼,在時間軸組件中使用connect鏈接了timeline和alertList兩個數據,其中,alertList數據是詳情內種中對應的告警列表。兩組數據對應的更改都會映射到組件的更新,好比時間軸的展開收起,以及alertList請求,請求成功及失敗等。

clipboard.png

按理來講,alertList對應的請求,僅對應到當前展開內容的更新便可。所以,咱們對此有幾種修改方案:

  1. 時間軸組件中棄用對alertList的引用,以保證alertList不會牽連到時間軸組件總體更新
  2. 將時間軸的渲染和詳情渲染進行分離,向其傳遞各自對應的數據,經過PureComponent來控制更新
  3. 使用shouldComponentUpdate進行優化

在此咱們採用第一種,避免alertList對整個組件的影響。

咱們會發現,點開詳情後,整個timeLine只進行了一次大更新,詳情的更新只在展開的組件中進行。

clipboard.png

優化點2

咱們會發現,在對某一個時間點進行展開時,整個list列表的節點都進行了更新,以下圖所示。顯然這樣的性能耗費是及其大且不重要的。假如列表的內容不少,那極有可能形成大量的更新致使頁面卡死。

clipboard.png

由於其餘的list列表節點都引用了alertList這個prop, 當其進行改變時,全部的節點都會進行更新,因此咱們須要使用shouldComponentUpdate手動對其進行優化:

// 當開關狀態變化時,才重新渲染,不然不須要
shouldComponentUpdate (nextProps, nextState) {
  const opened = _.get(this.props, 'open')
  const willOpen = _.get(nextProps, 'open')
  if (opened === willOpen && !willOpen) {
    return false
  } else {
    // 相似pureComponent進行淺比較
    return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState)
  }
}

再次進行錄製,咱們發現只要當前Item進行了更新,整個Timeline更新時間縮短到不到40ms,極大的增長了體驗。

clipboard.png

其餘優化過程與上面相似,再也不贅述。

總結

經過配合performance工具進行一步步優化,整個頁面的渲染和更新性能有了極大的提高,咱們也藉此知道了在平時書寫代碼過程當中須要注意的問題。咱們簡單的作一下總結:

  1. 避免非展現狀態的沒必要要的渲染
  2. 必要時,手動進行懶加載以免大型模塊對頁面進行營銷,避免加載沒必要要的模塊
  3. 保證展現組件props的純淨性,避免因其餘props的更改致使組件進行更新
  4. 必要時,可以使用shouldComponent進行手動優化
  5. 平時可經過PureComponent來避免沒必要要的組件更新
相關文章
相關標籤/搜索