網站性能優化--CRP

網站性能優化–CRP

為了把HTML、CSS和JavaScript轉化成活靈活現、絢麗多彩的網頁,瀏覽器需要處理一系列的中間過程,優化性能其實就是了解這個過程中發生了什么-即CRP(Critical Rendering Path,關鍵渲染路徑)。首先,我們從頭開始快速學習一下瀏覽器是如何顯示一個簡單網頁的。

瀏覽器渲染一個網頁的過程


構建對象模型

文檔對象模型(DOM)

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"><title>Critical Path</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body>
</html>

一個普通的頁面,里面包含一些文本和一張圖片,瀏覽器是如何處理這個頁面的呢?
這里寫圖片描述

  1. 轉換:瀏覽器從磁盤或網絡讀取HTML的原始字節,然后根據指定的文件編碼格式(例如 UTF-8)將其轉換為相應字符
  2. 令牌化:瀏覽器把字符轉化成W3C HTML5 標準指定的各種確切的令牌,比如””、””以及其他在尖括號內的字符串。每個令牌都有特殊的含義以及它自己的一套規則
  3. 詞法分析:生成的令牌轉化為對象,這個對象定義了它們的屬性及規則
  4. DOM構建:最后,由于HTML標記定義了不同標簽之間的關系(某些標簽嵌套在其他標簽中),創建的對象在樹狀的數據結構中互相鏈接,樹狀數據結構也捕獲了原始標簽定義的父子關系:HTML對象是body對象的父對象,body是p對象的父對象等等
    這里寫圖片描述
    上述整個流程的最終輸出是文檔對象模型,即這個簡單網頁的 “DOM”,瀏覽器完成頁面的所有后續處理都是建立在這個DOM基礎上的。
    打開Chrome DevTools > Timeline,錄制時間軸,上述過程對應Loading事件中的Parse HTML事件,可以查看到執行這一過程所需要的時間。
    DOM樹捕獲了文檔標記的屬性及關系,但它沒有告訴我們元素在渲染時是什么樣子的。這是CSSOM要干的活,也就是接下來要講的。

CSS對象模型(CSSOM)

當瀏覽器構建上述網頁DOM的時候,在head里面碰到一個link標簽,這個標簽引用了一個外部的CSS樣式表:style.css。瀏覽器預測會需要這個資源來渲染頁面,因此會立即發出一個該資源的請求,該請求返回以下內容:
與HTML一樣,我們需要將收到的 CSS 規則轉換為瀏覽器可以理解、能夠處理的東西。因此,我們重復與處理 HTML 非常相似的過程:
這里寫圖片描述
最終輸出的是CSS對象模型,即CSSOM。
這里寫圖片描述
想要查看CSS處理過程所花費的時間,可以在錄制的時間軸中查看Rendering事件中的Recalculate Style事件:與DOM解析不同,timeline不顯示單獨的“Parse CSS”條目,而是在Recalculate Style事件下一同捕獲CSS解析、CSSOM構建以及computed styles的遞歸計算。

構建渲染樹、布局及繪制

前面介紹了我們根據輸入的HTML及CSS構建了DOM樹和CSSOM樹,但二者是獨立的對象:DOM描述的是文檔內容,CSSOM描述的是應用于文檔的樣式規則。瀏覽器會把DOM和CSSOM組合起來構建一個渲染樹(Render-tree),渲染樹會捕獲頁面上所有可見的DOM內容以及應用在每個節點上的CSSOM樣式。
這里寫圖片描述

構建渲染樹的過程大致如下:

1.從DOM樹的根節點開始,遍歷每個可見的節點

  • 某些節點不可見(例如 script 標簽、meta 標簽等),因為它們不會體現在渲染結果中,所以會被忽略
  • 某些通過 CSS 隱藏的節點在渲染樹中也會被忽略,比如應用了 display:none 規則的節點

2.為每一個可見的節點匹配并應用對應的CSSOM規則
3.生成有內容和計算樣式的可見節點

注意:小提示:注意visibility: hidden和display: none二者的區別。visibility: hidden只是讓元素在視覺上不可見,但是元素在頁面布局中仍然占據空間。而display: none則是從渲染樹中刪除某一個元素,不僅視覺上不可見,渲染樹上也沒有,更不會影響到頁面的布局。
最終輸出的就是一個包含了所有可見節點的內容及樣式信息的渲染樹。

到目前為止,我們已經計算出了哪些節點是可見的以及它們的計算樣式,但是我們還沒有計算它們在設備視口(viewport)中的準確位置及尺寸大小——這就是布局(Layout)階段要做的工作,也就是常說的重排(reflow)

為了計算出頁面中每個對象的準確大小和位置,瀏覽器從渲染樹的根節點開始遍歷,計算頁面上每個對象的幾何信息。舉例如下:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>Critial Path: Hello world!</title></head><body><div style="width: 50%"><div style="width: 50%">Hello world!</div></div></body>
</html>

上面頁面的 body 包含兩個嵌套 div:第一個 div(父元素)將節點尺寸大小設置為視口寬度的 50%,第二個 div 的寬度為父元素的 50%,即視口寬度的 25%!
這里寫圖片描述

布局過程的輸出是一個“盒子模型”,它精確地捕獲了每個元素在視口中的準確位置及尺寸大小:所有相對度量單位都被轉換為屏幕上的絕對像素。

自此,我們已經知道了哪些節點是可見的以及它們的計算樣式和幾何信息,然后我們就可以把這些信息傳送到最后一個階段,即把渲染樹中的每一個節點都轉化到屏幕上實際的像素點。這個步驟通常被稱為繪制(painting)或者柵格化(rasterizing)

構建渲染樹、布局與繪制所消耗的時間也可以通過timeline來查看:
這里寫圖片描述

  • “Layout” 事件捕獲渲染樹的構建及位置、尺寸的計算
  • 布局完成時,瀏覽器會觸發 ‘Paint’ 事件:將渲染樹轉化為屏幕上的實際像素

終于,我們的頁面在設備視口中可見了。
這里寫圖片描述

現在回顧一下瀏覽器執行的幾個步驟:

  • 處理 HTML 標記,構建 DOM 樹
  • 處理 CSS 標記,構建 CSSOM 樹
  • 將 DOM 樹和 CSSOM 樹融合成渲染樹
  • 根據渲染樹進行布局,計算每個節點的幾何信息
  • 在屏幕上繪制各個節點

優化CRP

阻塞渲染的CSS

在構建渲染樹部分我們已了解到:CRP要求DOM和CSSOM兩者融合在一起才能構建渲染樹。這就導致了一個性能問題:HTML和CSS都是阻塞渲染的資源。HTML很顯然,沒有DOM就沒有內容去渲染。CSS沒有那么明顯,但確實是阻塞渲染的資源。我們知道一個正常的網頁如果沒有引入專用的css,頁面有多丑陋。當我們的網頁引入了專用的css,頁面一加載出來的時候就是絢麗多彩的,如果css不阻塞渲染,我們看到的很可能是這樣的一個畫面:頁面剛加載出來的時候其丑無比,過了一會,頁面又變漂亮了……

既然CSS是阻塞渲染的資源,這就意味著在CSSOM構建完成之前,瀏覽器不會去渲染任何已處理的內容。要盡早、盡快地把CSS下載到客戶端以優化首次渲染的時間。

使用CSS“媒體類型”和“媒體查詢”優化阻塞渲染的CSS:

<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
  • 第一條聲明阻塞渲染,匹配所有情況
  • 第二條聲明只適用于打印(媒體類型),因此,頁面在瀏覽器中首次加載時,不會阻塞渲染
  • 第三條聲明提供了媒體查詢,由瀏覽器判斷:如果條件符合,則在該樣式表下載并處理完以前,瀏覽器會阻塞渲染

小提示:「阻塞渲染」僅是指該資源是否會阻塞瀏覽器的首次頁面渲染。無論 CSS 是否阻塞渲染,CSS 資源都會被下載,只是說非阻塞性資源的優先級比較低而已。

阻塞解析的JavaScript

js可以修改頁面的內容、樣式以及響應用戶的交互,JS在DOM、CSSOM和JS執行之間引入了很多新的依賴關系,導致瀏覽器在處理和渲染頁面上出現大幅延遲:

  • 當瀏覽器遇到<script>標簽時,DOM構建會暫停,直到腳本執行完畢
  • JavaScript 執行會暫停,直到CSSOM準備就緒

解析器阻塞 vs. 異步 JavaScript

默認情況下,JavaScript 執行會阻塞解析器:當瀏覽器在文檔中遇到<script>標簽時,DOM構建必須暫停,瀏覽器把控制權移交給JS引擎,JS引擎編譯并執行腳本,腳本執行完畢后再繼續構建DOM。

事實上,內聯腳本始終會阻塞解析器,除非你編寫額外的代碼來延遲它們的執行。那通過<script>引入的外聯腳本呢?結果是一樣的,瀏覽器都會暫停,然后執行腳本,腳本執行完畢之后再去處理文檔的剩余部分。盡管如此,通過<script>引入外聯腳本還是有一個很大的好處。

默認情況下,所有 JS 均會阻塞解析器,因為瀏覽器不知道腳本想在頁面上做什么,因此它必須假定最糟的情況并阻塞解析器。但是,如果我們能夠有個信號告知瀏覽器,說腳本無需在文檔中引用它的確切位置被執行呢?這樣一來,瀏覽器就會繼續構建DOM,并在腳本準備就緒后執行腳本。

這個信號就是async——在script標簽里面添加async關鍵字,其有兩個特性:

  • 告訴瀏覽器當它碰到<script>標簽時不用阻塞DOM構建,因此瀏覽器會忽略腳本請求,繼續解析DOM
  • JS執行不依賴CSSOM:如果在CSSOM就緒之前腳本已經就緒,腳本可以立即執行
    很顯然,這將會顯著提升性能!

分析CRP性能

先定義三個用于描述CRP的詞匯:

  • 關鍵資源:能夠阻止網頁首次渲染的資源
  • 關鍵路徑長度:往返過程的數量,或者獲取所有關鍵資源所需的總時間
  • 關鍵字節:網頁首次渲染所需的總字節數,是所有關鍵資源的傳輸文件大小總和

demo1:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>Critical Path: No Style</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body>
</html>

最簡單的可用網頁僅由 HTML 標記組成:無 CSS、javascript 或其他類型的資源。要呈現此網頁,瀏覽器必須初始化請求、等待 HTML 文檔準備就緒、對其進行解析、構建 DOM,最后使其呈現在屏幕上。
這里寫圖片描述

  • 1個關鍵資源
  • 1個關鍵路徑長度(假設文件很小)
  • 5KB關鍵字節
    T0 和 T1 之間的時間用于捕獲網絡傳輸和服務器處理時間。 在最理想的情況(HTML 文件較小)下,我們僅需一個網絡往返過程即可提取整個文檔(由于 TCP 傳輸協議的工作方式,較大的文件可能需要多個往返過程)。

demo2:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body>
</html>

這里寫圖片描述

  • 2個關鍵資源
  • 2個或更多個關鍵路徑長度
  • 9KB關鍵字節

    我們必須同時使用 HTML 和 CSS 來構建渲染樹,因此 HTML 和 CSS 均為關鍵資源;瀏覽器需要一個網絡往返過程來提取 HTML 文檔,然后檢索到的標記告知我們還需要 CSS 文件,這意味著,瀏覽器必須返回服務器并獲取 CSS,然后才能在屏幕上呈現網頁,因此,該網頁最少需要兩個往返過程才能顯示(CSS 文件可能需要多個往返過程,重點在’最少’);兩種資源加起來的關鍵字節總量最多為 9 KB。

demo3:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js"></script></body>
</html>

這里寫圖片描述

  • 3個關鍵資源
  • 2個或更多個關鍵路徑長度
  • 11KB關鍵字節

    我們有三個關鍵資源,關鍵字節總量最多為 11 KB,但是關鍵路徑長度仍然是兩個往返過程,因為我們可以并行傳輸 CSS 和 JavaScript!

demo4: 如果app.js中的內容不涉及到操作DOM和CSSOM,只是一些分析類型的代碼和其他不需要阻塞頁面渲染的代碼,則可以在<script>中加入“async”屬性:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js" async></script></body>
</html>

這里寫圖片描述

異步執行腳本有以下幾項優勢:

  • 腳本再也不會阻止解析器,所以也不再是CRP的組成部分
  • 因為沒有其他關鍵腳本,CSS 也不需要阻止DomContentLoaded事件
  • DomContentLoaded事件觸發得越早,其他應用邏輯執行的時間就越早

因此,經過優化的網頁恢復到了具有兩個關鍵資源(HTML 和 CSS)、具有兩個往返過程的最短關鍵路徑長度和 9 KB 的關鍵字節總量。

demo5:

如果CSS樣式表僅適用于打印:

<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet" media="print"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js" async></script></body>
</html>

這里寫圖片描述

因為 style.css 資源僅用于打印,所以只要DOM構建完成,瀏覽器就具有了渲染網頁的足夠信息! 所以,該網頁僅具有一個關鍵資源(HTML),最小關鍵呈現路徑長度為一個往返過程和5KB的關鍵字節。

優化CRP

常規步驟:

  1. 分析、描述關鍵路徑:關鍵資源數量、字節數、關鍵路徑長度
  2. 最小化關鍵資源數量:刪除相應資源、延遲下載、標記為異步資源等
  3. 減少關鍵字節數,以減少資源下載時間(往返次數)
  4. 優化剩余關鍵資源的加載順序:盡可能早的下載所有關鍵資源,以縮短關鍵路徑長度

文章轉載自https://segmentfault.com/a/1190000008550336

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249693.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249693.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249693.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dubbo+zookeeper基礎講解

一、dubbo是什么&#xff1f; 1&#xff09;本質&#xff1a;一個Jar包,一個分布式框架,&#xff0c;一個遠程服務調用的分布式框架。 既然是新手教學&#xff0c;肯定很多同學不明白什么是分布式和遠程服務調用&#xff0c;為什么要分布式&#xff0c;為什么要遠程調用。我簡…

What Are You Talking About HDU1075

一開始我也想用map 但是處理不好其他字符。。 看了題解 多多學習&#xff01; 很巧妙 就是粗暴的一個字符一個字符的來 分為小寫字母和非小寫字母兩個部分 一但單詞結束的時候就開始判斷。 #include<bits/stdc.h> using namespace std;int main() {string a,b;map&l…

開通博客第一天

今天是開通博客第一天&#xff0c; 第一次寫博客&#xff0c;也不知道寫什么&#xff0c; 以后寫點技術文&#xff0c;把我的經驗分享給大家&#xff0c; 不對的地方請大家指正&#xff0c;一起進步。我要把我每遇到的難題以及學到的知識和技術為大家踩坑&#xff0c; 做研究。…

學習File API用于前端讀取文件

1. File API簡介 File API對于某些專門的網站的不可或缺的。現在常用它實現對文件的預覽等功能。 File API規定怎么從硬盤上提取文件&#xff0c;直接交給在網頁中運行中的Javascript代碼。然后代碼可以打開文件探究數據&#xff0c;無論是本地文件還是其他文件。注意&#x…

kafka筆記1

Kafka是一款基于發布和訂閱的消息系統。一般被稱為分布式提交日志或分布式流平臺。 Kafka系統是按照一定的順序持久化保存的&#xff0c;可以按需讀取。 Kafka的數據單元被稱為消息。類似于數據庫中表的一行記錄&#xff0c;消息由字節組成&#xff0c;所以沒有特別的格式和含義…

Dubbo入門教程

服務端&#xff08;dubbo-server&#xff09; 1. pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaL…

NSAssert和NSParameterAssert

2016.05.05 18:34* 字數 861 閱讀 5127評論 0喜歡 17https://www.jianshu.com/p/3072e174554fNSAssert和NSParameterAssert在開發環境中經常被使用&#xff0c;調試和驗證代碼參數的完整性&#xff0c;斷言為真&#xff0c;則表明程序運行正常&#xff0c;而斷言為假&#xff0…

【PAT】B1070 結繩(25 分)

此題太給其他25分的題丟人了&#xff0c;只值15分 注意要求最終結果最長&#xff0c;而且向下取整 #include<stdio.h> #include<algorithm> using namespace std; float arr[10005]; int main(){int N;scanf("%d",&N);for(int i0;i<N;i)//輸入數據…

Java代碼實現負載均衡五種算法

前言&#xff1a; 負載均衡是為了解決并發情況下&#xff0c;多個請求訪問&#xff0c;把請求通過提前約定好的規則轉發給各個server。其中有好幾個種經典的算法。在用java代碼編寫這幾種算法之前&#xff0c;先來了解一下負載均衡這個概念。 1.概念 負載&#xff0c;從字面…

使用Nodejs發送郵件

嘗試用了Nodemailer來發送郵件&#xff0c;結果成功了&#xff0c;雖然是相對比較簡單的&#xff0c;但還是記錄一下吧。 Nodemailer 是 Node.js 應用程序的一個模塊&#xff0c;可以方便地發送電子郵件。 使用 # 初始化 pageage.json 文件 $ npm init # 安裝依賴 $ npm ins…

HTTP同源策略

同源策略是web安全策略中的一種&#xff0c;非常重要。 同源策略明確規定&#xff1a;不同域的客戶端在沒有明確授權的情況下&#xff0c;不能讀寫對方的資源。 簡單說來就是web瀏覽器允許第一個頁面的腳本訪問訪問第二個頁面的數據&#xff0c;但是也只有在兩個頁面有相同的…

Spring Cloud 微服務架構

一、分布式服務框架的發展 1.1 第一代服務框架   代表&#xff1a;Dubbo(Java)、Orleans(.Net)等 特點&#xff1a;和語言綁定緊密 1.2 第二代服務框架   代表&#xff1a;Spring Cloud等 現狀&#xff1a;適合混合式開發&#xff08;例如借助Steeltoe OSS可以讓ASP.Ne…

JZOJ 4421. aplusb

4421. aplusb Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits Goto ProblemSetDescription SillyHook要給小朋友出題了&#xff0c;他想&#xff0c;對于初學者&#xff0c;第一題肯定是ab 啊&#xff0c;但當他出完數據后神奇地發現.in不見了&#xff0c…

跨域資源共享CORS詳解

最近深入了解了CORS的相關東西&#xff0c;覺得阮一峰老師的文章寫得最詳細易懂了&#xff0c;所有轉載作為學習筆記。 原文地址&#xff1a;跨域資源共享 CORS 詳解 CORS是W3C的一個標準&#xff0c;全稱是跨域資源共享&#xff08;Cross-origin resource sharing&#xff0…

計算機網絡(十),HTTP的關鍵問題

目錄 1.在瀏覽器地址欄鍵入URL&#xff0c;按下回車之后經歷的流程 2.HTTP狀態碼 3.GET請求和POST請求的區別 4.Cookie和Session的區別 5.IPV4和IPV6 十、HTTP的關鍵問題 1.在瀏覽器地址欄鍵入URL&#xff0c;按下回車之后經歷的流程 &#xff08;1&#xff09;DNS解析 &#x…

云技術

云技術是指在廣域網或局域網內將硬件、軟件、網絡等系列資源統一起來&#xff0c;實現數據的計算、儲存、處理和共享的一種托管技術。

vue中 mock使用教程

//mock/index.js import Mock from mockjs //引入mockjs&#xff0c;npm已安裝 import { Random,toJSONSchema } from mockjs // 引入random對象,隨機生成數據的對象&#xff0c;&#xff08;與占位符一樣&#xff09; Mock.setup({timeout:1000 //設置請求延時時間 }) const …

前端開發掌握nginx常用功能之rewrite

上一篇博文對nginx最常用功能的server及location的匹配規則進行了講解&#xff0c;這也是nginx實現控制訪問和反向代理的基礎。掌握請求的匹配規則算是對nginx有了入門&#xff0c;但是這些往往還是不能滿足實際的需求場景&#xff0c;例如請求url重寫、重定向等等&#xff0c;…

vue2.0腳手架的webpack 配置文件分析

前言 作為 Vue 的使用者我們對于 vue-cli 都很熟悉&#xff0c;但是對它的 webpack 配置我們可能關注甚少&#xff0c;今天我們為大家帶來 vue-cli#2.0 的 webpack 配置分析 vue-cli 的簡介、安裝我們不在這里贅述&#xff0c;對它還不熟悉的同學可以直接訪問 vue-cli 查看 …

一個可供中小團隊參考的微服務架構技術棧

一個可供中小團隊參考的微服務架構技術棧