前端Dom層次性能優化----簡單講解

從輸入 URL 到頁面加載完成,完整的鏈路

 

 

 

 

http層面優化

  • DNS 解析:
    DNS 實現域名到IP的映射。經過域名訪問站點,每次請求都要作DNS解析。目前每次DNS解析,一般在200ms如下。通常採用DNS Prefetch 一種DNS 預解析技術,當你瀏覽網頁時,瀏覽器會在加載網頁時對網頁中的域名進行解析緩存,這樣在你單擊當前網頁中的鏈接時就無需進行DNS的解析,減小用戶等待時間,提升用戶體驗。
<link rel="dns-prefetch" href="www.baidu.com" /> 只有部分瀏覽器支持
  • TCP 鏈接:
    採用http2.0,能夠複用tcp通道,採用二進制格式而非文本格式,使用報頭壓縮,HTTP/2下降了開銷,支持cache pushcss

  • 瀏覽器併發
    基於端口跟線程切換開銷,瀏覽器不可能無限的併發請求。chrome的併發爲6,超過限制數目的請求就會被阻塞;
    對於某些靜態資源,圖片等等,咱們能夠對其URL分散處理 ,不一樣的資源域名(部署在cdn上)。vue

  • http請求次數
    cdn託管,主要針對http緩存;雪碧圖;腳本合併;圖片懶加載;本地緩存;java

  • webpack
    充分利用webpack提供給咱們的能力,利用DllPlugin與commonPlugins等插件對咱們代碼進行
    優化,文件的分割與合併,公共代碼的提取,長緩存等策略,webpack是個很好的東西,值得你們仔細研究react

  • http壓縮
    採用Gzip壓縮:HTTP 壓縮就是以縮小體積爲目的,對 HTTP 內容進行從新編碼的過程,原理是找出一些重複出現的字符串、臨時替換它們,從而使整個文件變小,文件中代碼的重複率越高,那麼壓縮的效率就越高,使用 Gzip 的收益也就越大webpack

瀏覽器渲染

瀏覽器渲染機制

    • DOM樹:
      解析 HTML 以建立的是 DOM 樹(DOM tree ):渲染引擎開始解析 HTML 文檔,轉換樹中的標籤到 DOM 節點,它被稱爲「內容樹」。
    • CSSOM樹:
      解析 CSS(包括外部 CSS 文件和樣式元素)建立的是 CSSOM 樹。CSSOM 的解析過程與 DOM 的解析過程是並行的。
      -渲染樹:
      CSSOM 與 DOM 結合,以後咱們獲得的就是渲染樹(Render tree )。
    • 佈局渲染樹:
      從根節點遞歸調用,計算每個元素的大小、位置等,給每一個節點所應該出如今屏幕上的精確座標,咱們便獲得了基於渲染樹的佈局渲染樹(Layout of the render tree)。
    • 繪製渲染樹:
      遍歷渲染樹,每一個節點將使用 UI 後端層來繪製。整個過程叫作繪製渲染樹(Painting the render tree)。

當咱們瀏覽器得到HTML文件後,會自上而下的加載,並在加載過程當中進行解析和渲染。ios

加載說的就是獲取資源文件的過程,若是在加載過程當中遇到外部CSS文件和圖片,瀏覽器會另外發送一個請求,去獲取CSS文件和相應的圖片,這個請求是異步的,並不會影響HTML文件的加載。web

可是若是遇到Javascript文件,HTML文件會掛起渲染的進程,等待JavaScript文件加載完畢後,再繼續進行渲染。 爲何HTML須要等待JavaScript呢?由於JavaScript可能會修改DOM,致使後續HTML資源白白加載,因此HTML必須等待JavaScript文件加載完畢後,再繼續渲染,這也就是爲何JavaScript文件在寫在底部body標籤前的緣由。chrome

 

 

 

  重繪與重排express

當DOM的變化引起了元素幾何屬性的變化,好比改變元素的寬高元素的位置,致使瀏覽器不得不從新計算元素的幾何屬性,並從新構建渲染樹,這個過程稱爲「重排」。完成重排後,要將從新構建的渲染樹渲染到屏幕上,這個過程就是「重繪」。axios

簡單的說,重排負責元素的幾何屬性更新,重繪負責元素的樣式更新。並且,重排必然帶來重繪,可是重繪未必帶來重排。好比,改變某個元素的背景,這個就不涉及元素的幾何屬性,因此只發生重繪。

上面已經提到了,重排發生的根本原理就是元素的幾何屬性發生了改變,那麼咱們就從可以改變元素幾何屬性的角度入手

 重排觸發幾種情景:

  1. 添加或刪除可見的DOM元素
  2. 元素位置改變
  3. 元素自己的尺寸發生改變
  4. 內容改變
  5. 頁面渲染器初始化
  6. 瀏覽器窗口大小發生改變

 如何進行性能優化針對重排

重繪和重排的開銷是很是昂貴的,若是咱們不停的在改變頁面的佈局,就會形成瀏覽器耗費大量的開銷在進行頁面的計算,這樣的話,咱們頁面在用戶使用起來,就會出現明顯的卡頓。如今的瀏覽器其實已經對重排進行了優化,好比以下代碼:

 

比較久遠的瀏覽器,這段代碼會觸發頁面2次重排,在分別設置寬高的時候,觸發2次.

當代的瀏覽器對此進行了優化,這種思路相似於如今流行的MVVM框架使用的虛擬DOM,對改變的DOM節點進行依賴收集,確認沒有改變的節點,就進行一次更新。可是瀏覽器針對重排的優化雖然思路和虛擬DOM接近,可是仍是有本質的區別。大多數瀏覽器經過隊列化修改並批量執行來優化重排過程。也就是說上面那段代碼其實在如今的瀏覽器優化下,只構成一次重排。

可是仍是有一些特殊的元素幾何屬性會形成這種優化失效。好比:

 

 爲何形成優化失效呢?仔細看這些屬性,都是須要實時回饋給用戶的幾何屬性或者是佈局屬性,固然不能再依靠瀏覽器的優化,所以瀏覽器不得不當即執行渲染隊列中的「待處理變化」,並隨之觸發重排返回正確的值。

最小化重繪和重排

 既然重排&重繪是會影響頁面的性能,尤爲是糟糕的JS代碼更會將重排帶來的性能問題放大。既然如此,咱們首先想到的就是減小重排重繪。

 

 

 

 

批量修改DOM

批量修改DOM元素的核心思想是:

  • 讓該元素脫離文檔流
  • 對其進行多重改變
  • 將元素帶回文檔中

優化技巧:
1.DOM 的多個讀操做(或多個寫操做),應該放在一塊兒。不要兩個讀操做之間,加入一個寫操做。

2.不要一條條地改變樣式,而要經過改變class,或者csstext屬性,一次性地改變樣式。

3.儘可能使用離線DOM,而不是真實的網面DOM,來改變元素樣式。好比,DocumentFragment,或 cloneNode()

4.也能夠先 display: none ,而後隨便操做,最後再恢復顯示

5.position屬性爲absolute或fixed的元素,重排的開銷會比較小,由於不用考慮它對其餘元素的影響。

6.還能夠考慮,「只在必要的時候,纔將元素的display屬性爲可見」

7.使用虛擬DOM(vue, react)

8.window.requestAnimationFrame() 方法,就個是「節流」的思想,將代碼放到下一次從新渲染時執行。 頁面滾動事件(scroll)的監聽函數,還有網頁動畫,就很適合用 window.requestAnimationFrame()

還有另外一個,window.requestIdleCallback(),把函數放到瀏覽器的空閒時段內調用

9.若是你已經知道圖片的寬高了,你最好是寫在內聯樣式上。
這樣圖片在下載完以前,瀏覽器會根據你的寬高佔一個位置,若是沒有寬高,圖片下載下來後,整個頁面會發生重排。

10.緩存佈局信息
11.避免一些無用數據,減小重排次數
 

 

 

多餘的的重排

 

 

 

 

 

vue方面的一些例子

一、v-if 和 v-show 區分使用場景
  v-if 是 真正 的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建;也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。
  v-show 就簡單得多, 無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 的 display 屬性進行切換。
  因此,v-if 適用於在運行時不多改變條件,不須要頻繁切換條件的場景;v-show 則適用於須要很是頻繁切換條件的場景。
二、computed 和 watch 區分使用場景
  computed:**是計算屬性,依賴其它屬性值,而且 computed 的值有緩存,只有它依賴的屬性值發生改變,下一次獲取 computed 的值時纔會從新計算 computed 的值;
  watch:**更多的是「觀察」的做用,相似於某些數據的監聽回調 ,每當監聽的數據變化時都會執行回調進行後續操做;
  運用場景:
  當咱們須要進行數值計算,而且依賴於其它數據時,應該使用 computed,由於能夠利用 computed 的緩存特性,避免每次獲取值時,都要從新計算;當咱們須要在數據變化時執行異步或開銷較大的操做時,應該使用 watch,使用 watch 選項容許咱們執行異步操做 ( 訪問一個 API ),限制咱們執行該操做的頻率,並在咱們獲得最終結果前,設置中間狀態。這些都是計算屬性沒法作到的。


三、利用凍結數據
  Vue 會經過 Object.defineProperty 對數據進行劫持,來實現視圖響應數據的變化,然而有些時候咱們的組件就是純粹的數據展現,不會有任何改變,咱們就不須要 Vue 來劫持咱們的數據,在大量數據展現的狀況下,這可以很明顯的減小組件初始化的時間,那如何禁止 Vue 劫持咱們的數據呢?能夠經過 Object.freeze 方法來凍結一個對象,一旦被凍結的對象就不再能被修改了。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

四、事件的銷燬
  Vue 組件銷燬時,會自動清理它與其它實例的鏈接,解綁它的所有指令及事件監聽器,可是僅限於組件自己的事件。 若是在 js 內使用 addEventListene 等方式是不會自動銷燬的,咱們須要在組件銷燬時手動移除這些事件的監聽,以避免形成內存泄露,如:

created() {
  addEventListener('click', this.click, false)
},
beforeDestroy() {
  removeEventListener('click', this.click, false)
}

 

 總之:  減小對dom的操做;減小重排與重繪;

 

 

 CSS 方面

 

性能優化

 

慎重選擇高消耗的樣式

 

高消耗屬性在繪製前須要瀏覽器進行大量計算:

 

box-shadowsborder-radiustransparencytransformsCSS filters(性能殺手)

 

 

1.scope中元素選擇器儘可能少用

用途:防止全局同名CSS污染
原理:在標籤加上v-data-something屬性,再在選擇器時加上對應[v-data-something],即CSS帶屬性選擇器,以此完成相似做用域的選擇方式

缺點:
(1)因爲只是經過屬性限制,類仍是原來的類,因此在其餘地方對類設置樣式仍是能夠形成污染。
(2)添加了屬性選擇器,對於CSS選擇器的權重加劇了。
(3)外層組件包裹子組件,會給子組件的根節點添加data屬性。在外層組件中沒法修改子組件中除了根節點之外的節點的樣式。好比子組件中有box類,在父節點中設置樣式,會被編譯爲

.box[data-v-x]


2. 減小查詢層級:如.header .logo要好過.header .top .logo;

 3.減小查詢範圍:如.header>li要好過.header li;

4.避免tag標籤與class或者ID並存:如a.top、button#submit;

5.避免在CSS中使用運算式:expression、calc、等等,可能會形成屢次repaint和reflow。

6.不濫用 Float

Float在渲染時計算量比較大,儘可能減小使用。 flex 基本上 能夠比float佈局 節省一倍的時間

7.若是使用基於 javaScript 的動畫,儘可能使用 requestAnimationFrame.

避免使用 setTimeout, setInterval.避免經過相似 jQuery animate()-style 改變每幀的樣式,使用 CSS 聲明動畫會獲得更好的瀏覽器優化。

使用 translate 取代 absolute 定位就會獲得更好的 fps,動畫會更順滑。

8.善於css繼承

 

 

總之:CSS 優化主要是四個方面:

1.加載性能
這個方面相關的 best practice 太多了,網上隨便找一找就是一堆資料,好比不要用 import 啊,壓縮啊等等,主要是從減小文件體積、減小阻塞加載、提升併發方面入手的,任何 hint 都逃不出這幾個大方向。
2.選擇器性能
3.渲染性能
渲染性能是 CSS 優化最重要的關注對象。頁面渲染 junky 過多?看看是否是大量使用了 text-shadow?是否是開了字體抗鋸齒?CSS 動畫怎麼實現的?合理利用 GPU 加速了嗎?什麼你用了 Flexible Box Model?有沒有測試換個 layout 策略對 render performance 的影響?這個方面搜索一下 CSS render performance 或者 CSS animation performance 也會有一堆一堆的資料可供參考。
4.可維護性、健壯性
命名合理嗎?結構層次設計是否足夠健壯?對樣式進行抽象複用了嗎?優雅的 CSS 不只僅會影響後期的維護成本,也會對加載性能等方面產生影響。這方面能夠多找一些 OOCSS(不是說就要用 OOCSS,而是說多瞭解一下)等等不一樣 CSS Strategy 的信息,取長補短。
 
一、命名與備註

二、提取重複樣式

三、推薦書寫順序

(1)位置屬性(position, top, right, z-index, display, float等)

(2)大小(width, height, padding, margin)

(3)文字系列(font, line-height, letter-spacing, color- text-align等)

(4)背景(background, border等)

(5)其餘(animation, transition等)
相關文章
相關標籤/搜索