脫離996,Chrome DevTools 面板全攻略!!!

李華西,微醫雲服務團隊前端開發工程師,喜歡瞎折騰,典型貓奴javascript

Console 面板

此章節請打開 devtools/console/console.html 一塊兒食用css

一方面用來記錄頁面在執行過程當中的信息(通常經過各類 console 語句來實現),另外一方面用來當作 shell 窗口來執行腳本以及與頁面文檔、DevTools 等進行交互html

組合快捷鍵按鍵:
Windows: Control + Shift + J
Mac: Command + Option + J前端

首先看一下 console 對象下面都有哪些方法:
java

console.clear()

顧名思義,清空控制檯node

console.log(), info(), warn(), error()

平常用的比較多的就是這幾個了,其中 loginfo,印象中在 2016 年以前老用 info 打印,仍是有區別的,info 輸出的內容前面是有一個藍色背景的小圈, 大概跟這個差很少: i,後來 chrome 更新就沒了 (IE 仍是能夠看出差異的)webpack

console.log('普通訊息')
console.info('提示性信息')
console.error('錯誤信息')
console.warn('警示信息')
複製代碼
複製代碼

使用佔位符git

// 支持逗號分隔參數,不須要每一個參數都單獨打印
console.log(1, '2', +'3')
// 佔位符
// %s 
console.log('今晚%s 老虎', '打', '???')
// %c 
console.log('今晚%s%c 老虎', '打', 'color: red', '???')
// 帶有佔位符的參數以後的若干參數屬於佔位符的配置參數
複製代碼
複製代碼

其他的佔位符列表還有:github

佔位符 功能
%s 字符串
%d 整數
%i 整數
%f 浮點數
%o 對象的連接
%c css 格式字符串

console.time(), timeEnd()

timetimeEnd 通常放在一塊兒用,傳入一個參數用來標識起始位置用於統計時間:web

console.time('t')
Array(900000).fill({}).forEach((v, index) => v.index = index)
console.timeEnd('t')
// t: 28.18603515625ms
複製代碼
複製代碼

會打印出中間代碼的執行時間

console.count()

顧名思義。。計數, 能夠用來統計某個函數的執行次數,也能夠傳入一個參數,而且根據傳入的參數分組統計調用的次數

function foo(type = '') {
  type ? console.count(type) : console.count()
  return 'type:' + type
}

foo('A') //A: 1
foo('B') //B: 1
foo()    //default: 1
foo()    //default: 2
foo()    //default: 3
foo('A') //A: 2
複製代碼
複製代碼

console.trace()

用於追蹤代碼的調用棧,不用專門斷點去看了

console.trace()
function foo() {
  console.trace()
}
foo()
複製代碼
複製代碼

console.table()

console.table() 方法能夠將複合類型的數據轉爲表格顯示

var arr = [
  { name: '梅西', qq: 10 },
  { name: 'C 羅', qq: 7 },
  { name: '內馬爾', qq: 11 },
]
console.table(arr)
複製代碼
複製代碼

console.dir()

按便於閱讀和打印的形式將對象打印

var obj = {
  name: 'justwe7',
  age: 26,
  fn: function () {
    alert('justwe7')
  },
}
console.log(obj)
console.dir(obj)
複製代碼
複製代碼

打印 DOM 對象區別:

console.assert()

斷言,用來進行條件判斷。當表達式爲 false 時,則顯示錯誤信息,不會中斷程序執行。

能夠用於提示用戶,內部狀態不正確(把那個說假話的揪出來)

var val = 1
console.assert(val === 1, '等於 1')
console.assert(val !== 1, '不等於 1')
console.log('代碼往下執行呢啊')
複製代碼
複製代碼

console.group(), groupEnd()

分組輸出信息,能夠用鼠標摺疊 / 展開

console.group('分組 1')
console.log('分組 1-1111')
console.log('分組 1-2222')
console.log('分組 1-3333')
console.groupEnd()
console.group('分組 2')
console.log('分組 2-1111')
console.log('分組 2-2222')
console.log('分組 2-3333')
console.groupEnd()
複製代碼
複製代碼

$ 選擇器

$_

能夠記錄上次計算的結果,直接用於代碼執行:

$0,$1...$4

表明最近 5 個審查元素選中過的 DOM 節點,看圖(是要選中一下,我更喜歡用存儲全局變量的方式玩,省的本身手殘又選了一個節點):

$和?

  • $(selector)是原生 document.querySelector() 的封裝。
  • ?(selector)返回的是全部知足選擇條件的元素的一個集合,是 document.querySelectorAll() 的封裝

$x

將所匹配的節點放在一個數組裏返回

<ul>
  <ul>
    <li><p>li 下的 p1</p></li>
    <li><p>li 下的 p2</p></li>
    <li><p>li 下的 p3</p></li>
  </ul>
</ul>
<p>外面的 p</p>
複製代碼
複製代碼
$x('//li') // 全部的 li
$x('//p') // 全部的 p
$x('//li//p') // 全部的 li 下的 p
$x('//li[p]') // 全部的 li 下的 p
複製代碼
複製代碼

keys(), values()

跟 ES6 對象擴展方法, Object.keys()Object.values() 相同

keys(obj);
values(obj);
複製代碼
複製代碼

copy()

能夠直接將變量複製到剪貼板

copy(temp1)
複製代碼
複製代碼

Save global variable 結合使用神器

Element 面板

此章節請打開 devtools/element/element.html 一塊兒食用

在 Elements 面板中能夠經過 DOM 樹的形式查看全部頁面元素,同時也能對這些頁面元素進行所見即所得的編輯

組合快捷鍵按鍵:
Windows: Control + Shift + C
Mac: Command + Option + C

css 調試

style

選中目標節點,element 面版,查看 style->:hov, 選擇對應的狀態便可

computed

有時候樣式覆蓋過多,查看起來很麻煩,computed 就派上用場了

點擊某個樣式能夠直接跳轉至對應 css 定義

調整某個元素的數值

選中想要更改的值,按方向鍵上下就能夠 + / - 1 個單位的值

alt + 方向鍵 能夠 ×10 調整單位值
Ctrl + 方向鍵 能夠 ×100 調整單位值
shift + 方向鍵 能夠 /10 調整單位

html 調試

騷操做

選中節點,直接按鍵盤 H 能夠直接讓元素顯示 / 隱藏,不用手動敲樣式了,效果等同 visibility: hidden,仍是要佔據盒模型空間的。(記得把輸入法改爲英文~)

將某個元素存儲到全局臨時變量中

選中節點,右鍵,Store as global variable(在 network 面板中也能用,尤爲是篩選接口的返回值很方便)

滾動到某個節點

若是頁面很長,想找一個文本節點的顯示位置又不想手動滑動能夠試試 Scroll into view

Edge 專屬的 3D 視圖

使用 chromium 後的 Edge 真的是改頭換面,3D 視圖能夠幫忙定位一些定位層級還有 DOM 嵌套的問題,頁面結構寫的好很差看很直觀的能夠看出來 (跟輔助功能裏面的 dom 樹結合使用很舒服)

目前 chrome 仍是沒有這項功能的,Edge 打開位置:控制檯打開狀態 => Esc打開抽屜 => ···選擇 3D 視圖面板

DOM 斷點

能夠監聽到 DOM 節點的變動 (子節點變更 / 屬性變動 / 元素移除),並斷點至變動 DOM 狀態的 js 代碼行:

Network 面板

能夠查看經過網絡請求的資源的相關詳細信息

組合快捷鍵按鍵:
Windows: Control + Shift + I
Mac: Command + Option + I

按區域劃分大概分爲以下幾個區域:

  1. Controls - 控制 Network 功能選項,以及一些展現外觀

  2. Filters - 控制在 Requests Table 中顯示哪些類型的資源

    tips:按住 Cmd (Mac) 或 Ctrl (Windows/Linux) 並點擊篩選項能夠同時選擇多個篩選項

  3. Overview - 此圖表顯示了資源檢索時間的時間線。若是看到多條豎線堆疊在一塊兒,則說明這些資源被同時檢索

  4. Requests Table - 此表格列出了檢索的每個資源。 默認狀況下,此表格按時間順序排序,最先的資源在頂部。點擊資源的名稱能夠顯示更多信息。 提示:右鍵點擊 Timeline 之外的任何一個表格標題能夠添加或移除信息列

  5. Summary - 能夠一目瞭然地看到頁面的請求總數、傳輸的數據總量、加載時間

(一、2)Controls,Filters 區域

Filters 控制的展現:

  • 使用大請求行 - 默認狀況下,Requests Table一個資源只顯示很小的一行。選中Use large resource rows(使用大資源行) 按鈕能夠顯示兩個文本字段:主要字段和次要字段。
  • 捕獲屏幕截圖 - 將鼠標懸停在某個屏幕截圖上的時候,Timeline/Waterfall(時間軸) 會顯示一條垂直的黃線,指示該幀是什麼時候被捕獲的
  • 顯示概述 - 展現頁面整個生命週期的各個階段(Overview 區域)的耗時(藍色綠色的那些橫槓)

(3) Overview 區域

頁面整個生命週期的各個階段網絡資源加載耗時信息的彙總,能夠選擇區域來篩選 Requests Table 的詳細資源信息

(4) Requests Table 區域

標題欄的對應描述:

  • Name(名稱): 資源的名稱。
  • Status(狀態): HTTP 狀態代碼。
  • Type(類型): 請求的資源的 MIME 類型。
  • Initiator(發起): 發起請求的對象或進程。它可能有如下幾種值:
    • Parser(解析器): Chrome 的 HTML 解析器發起了請求。
    • Redirect(重定向): HTTP 重定向啓動了請求。
    • Script(腳本): 腳本啓動了請求。
    • Other(其餘): 一些其餘進程或動做發起請求,例如用戶點擊連接跳轉到頁面,或在地址欄中輸入網址。
  • Size(大小): 響應頭的大小(一般是幾百字節)加上響應數據,由服務器提供。
  • Time(時間): 總持續時間,從請求的開始到接收響應中的最後一個字節
  • Timeline/Waterfall(時間軸): 顯示全部網絡請求的可視化統計信息

在標題欄如 (Name 上) 右鍵,能夠添加或刪除信息列。好比能夠多加一列 Response Header => Content-Encoding 選項來總覽頁面資源的 gzip 壓縮狀況:

從新發起xhr請求

在平時和後端聯調時,咱們用的最多的可能就是Network面板了。可是每次想從新查看一個請求經過刷新頁面、點擊按鈕等方式去觸發xhr請求,這種方式有時顯得會比較麻煩,能夠經過Replay XHR的方式去發起一條新的請求:

查看 HTTP 相關信息

查看網絡請求的參數

能夠經過點擊 query string parameters (查詢字符串參數) 旁邊的 view URL encoded (查看 URL 編碼) 或 view decoded (查看解碼) 連接,查看 URL 編碼或解碼格式的 query string parameters (查詢字符串參數)。在使用 postman 複製相關入參時尤爲實用。

查看 HTTP 響應內容 點擊 Response(響應) 標籤頁能夠查看該資源未格式化的 HTTP 響應內容

接口的返回值 (在 preview 中)一樣也能夠 Save global variable 存儲一個全局變量

Size 和 Time 爲何有兩行參數?

關於 Size 列

Size有兩行:

  • 第一行表示的是數據的傳輸時的大小,例如上圖中的190KB
  • 第二行表示的是數據實際的大小708KB

在服務器端採起gzip壓縮算法將原有708KB壓縮至190KB, 傳輸大小縮短3.7 倍,大大的提升了資源傳輸的效率

須要注意的點:

gzip壓縮只會壓縮響應體內容,因此適用於返回數據量大的時候,若是數據量過小的話,有可能會致使數據傳輸時的大小比實際大小要大 (加入了一些額外的響應頭)

關於 Time 列

Time 有兩行:

  • 第一行表示從客戶端發送請求到服務端返回全部數據所花費的總時間,對於上圖來講就是471ms
  • 第二行表示的是從客戶端發送請求到服務器端返回第一個字節所表示的時間,對於上圖來講就是55ms

第一行的時間表明瞭全部項目:例如解析 dns創建鏈接等待服務器返回數據傳輸數據

第二行的時間是 總時間 - 數據傳輸的時間

從上面的分析中咱們看到 從客戶端請求到服務器處理結束準備返回數據花了55ms,可是在進行傳輸數據的時候花費了471ms

對於網慢的用戶來講,可能會耗費更長的時間,因此在寫代碼(接口)的時候,返回的數據量要儘可能精簡

Waterfall

點擊某個資源會展現出詳細的網絡加載信息:

相關字段描述:

  • Queuing (排隊)

    瀏覽器在如下狀況下對請求排隊

    1. 存在更高優先級的請求, 請求被渲染引擎推遲,這常常發生在 images(圖像)上, 由於它被認爲比關鍵資源(如腳本 / 樣式)的優先級低。
    2. 此源已打開六個 TCP 鏈接,達到限值,僅適用於 HTTP/1.0 和 HTTP/1.1。在等待一個即將被釋放的不可用的 TCP socket
    3. 瀏覽器正在短暫分配磁盤緩存中的空間,生成磁盤緩存條目(一般很是快)
  • Stalled (停滯) - 發送請求以前等待的時間。它可能由於進入隊列的任意緣由而被阻塞,這個時間包括代理協商的時間。請求可能會因 Queueing 中描述的任何緣由而中止。

  • DNS lookup (DNS 查找) - 瀏覽器正在解析請求 IP 地址,頁面上的每一個新域都須要完整的往返 (roundtrip) 才能進行 DNS 查找

  • Proxy Negotiation - 瀏覽器正在與代理服務器協商請求

  • initial connection (初始鏈接) - 創建鏈接所需的時間,包括 TCP 握手 / 重試和協商 SSL。

  • SSL handshake (SSL 握手) - 完成 SSL 握手所用的時間

  • Request sent (請求發送) - 發出網絡請求所花費的時間,一般是幾分之一毫秒。

  • Waiting (等待) - 等待初始響應所花費的時間,也稱爲Time To First Byte(接收到第一個字節所花費的時間)。這個時間除了等待服務器傳遞響應所花費的時間以外,還包括 1 次往返延遲時間及服務器準備響應所用的時間(服務器發送數據的延遲時間)

  • Content Download(內容下載) - 接收響應數據所花費的時間 (從接收到第一個字節開始,到下載完最後一個字節結束)

  • ServiceWorker Preparation - 瀏覽器正在啓動 Service Worker

  • Request to ServiceWorker - 正在將請求發送到 Service Worker

  • Receiving Push - 瀏覽器正在經過 HTTP/2 服務器推送接收此響應的數據

  • Reading Push - 瀏覽器正在讀取以前收到的本地數據

(5) Summary 區域

requests 查看請求的總數量 | transferred 查看請求的總大小 | resources 資源 | Finish 全部 http 請求響應完成的時間 | DOMContentLoaded 時間 | load 時間

當頁面的初始的標記被解析完時,會觸發 DOMContentLoaded。 它在 Network(網絡) 面板上的顯示:

  • 在 Overview (概覽) 窗格中的藍色垂直線表示這個事件。
  • 在 Requests Table (請求列表) 中的紅色垂直線也表示這個事件。
  • 在 Summary (概要) 窗格中,您能夠查看事件的確切時間。

當頁面徹底加載時觸發 load 事件。 它顯示也顯示在:

  • 在 Overview (概覽) 窗格的紅色垂直線表示這個事件。
  • 在 Requests Table (請求列表) 中的紅色垂直線也表示這個事件。
  • 在 Summary (概要) 中,能夠查看改事件的確切時間

DOMContentLoaded 會比 Load 時間小,二者時間差大體等於外部資源加載(通常是圖片 / 字體)的時間

Finish 時間是頁面上全部 http 請求發送到響應完成的時間(若是頁面存在一個輪詢的接口,這個值也會累加的)。HTTP1.0/1.1 協議限定單個域名的請求併發量是 6 個,即 Finish 是全部請求(不僅是 XHR 請求,還包括 DOC,img,js,css 等資源的請求)在併發量爲 6 的限制下完成的時間。

  • Finish 的時間比 Load 大,意味着頁面有至關部分的請求量
  • Finish 的時間比 Load 小,意味着頁面請求量不多,若是頁面是隻有一個 html 文檔請求的靜態頁面,Finish 時間基本就等於 HTML 文檔請求的時間

因此 Finish 時間與 DOMContentLoaded 和 Load 並沒有直接關係

使用 Network 面板進行網絡優化

參考 Network 面板能夠針對 Network 提出一些優化建議

排隊或中止阻塞

最多見的問題是不少個請求排隊或被阻塞。這表示從單個客戶端檢索的資源太多。在 HTTP 1.0/1.1 鏈接協議中,Chrome 限制每一個域名最多執行 6 個 TCP 鏈接。若是一次請求十二個資源,前 6 個將開始,後 6 個將排隊。一旦其中一個請求完成,隊列中的第一個請求項目將開始其請求過程。

要解決傳統 HTTP 1 的此問題,須要用多個子域名提供服務資源,將資源拆分到多個子域中,均勻分配。

上面說的修復 HTTP 1 鏈接數問題,不適用於 HTTP 2 鏈接,若是已部署 HTTP 2,不要對資源進行域劃分,由於它會影響 HTTP 2 的工做原理(在 HTTP 2 中 TCP 鏈接多路複用鏈接的)。取消了 HTTP 1 的 6 個鏈接限制,而且能夠經過單個鏈接同時傳輸多個資源。

接收到第一個字節的時間很慢

綠色的塊佔據比例很高:

TTFB 就是等待第一個響應字節的時間,建議在 200ms 如下,如下狀況可能會致使高 TTFB:

  1. 客戶端和服務器之間的網絡條件差
  2. 要麼,服務器端程序響應很慢

爲了解決高 TTFB,首先去排除儘量多的網絡鏈接。理想狀況下,在本地託管應用程序(部署在本地),並查看是否仍有一個大的 TTFB。若是有,那麼須要優化應用程序針的響應速度。這可能意味着優化數據庫查詢,爲內容的某些部分實現高速緩存,或修改 Web 服務器配置。後端可能很慢的緣由有不少。您須要對您的程序進行研究,並找出不符合您預期的內容。

若是本地 TTFB 低,那麼是您的客戶端和服務器之間的網絡問題。網絡傳輸可能被不少種事情干擾阻礙。在客戶端和服務器之間有不少點,每一個都有本身的鏈接限制,可能會致使問題。測試減小這種狀況的最簡單的方法是將您的應用程序放在另外一臺主機上,看看 TTFB 是否改進。

加載緩慢

藍色的塊佔據比例很高:

若是 Content Download (內容下載) 階段花費了不少時間,提升服務響應速度、並行下載等優化措施幫助都不大。 主要的解決方案是發送更少的字節(好比一張高質量的大圖可能幾 M 的大小,這時能夠酌情優化一下圖片的寬高 / 清晰度)

Sources 面板

此章節請打開 /devtools/debug-js/get-started.html 一塊兒食用

主要用來調試頁面中的 JavaScript

自定義代碼片斷 Snippets

咱們常常有些 JavaScript 的代碼想在控制檯中調試,假如代碼量多的狀況下直接在 console 下寫比較麻煩,或者咱們常常有些代碼片斷 (防抖、節流、獲取地址欄參數等) 想保存起來,每次打開 Devtools 都能獲取到這些代碼片斷,而不用再去從筆記裏面找。

如圖所示,在 Sources 這個tab欄下,有個 Snippets 標籤,在裏面能夠添加一些經常使用的代碼片斷。(當個小筆記本)

設置斷點

斷點的面板

指定位置的中斷

斷點調試基本流程

找到源代碼,點擊要中斷代碼執行的位置,點擊紅色按鈕的位置。而後再觸發該方法執行,由於已知點擊按鈕能夠觸發,精準的定位到代碼行就能夠了:

全局事件中斷

假如不知道代碼執行的位置,如如下場景:

看接口返回的列表總數應該是 20 條,可是頁面到 15 條就顯示到底部了

看代碼寫的判斷條件有點問題,但從編譯後的代碼找到對應位置進行調試就至關於大海撈針了。想試試本身的設想的解決方式是否正確:

  1. 由於列表是提拉加載,因此確定會觸發網絡請求,能夠在事件偵聽器裏面打一個 XHR 的斷點

  2. 而後提拉加載頁面觸發接口請求,如預期的,代碼中斷執行了。但提示找不到 sourcemap,暫時把 js 的資源映射給關掉 (相關解決方式)

  3. 再次觸發斷點,發現能夠查看到中斷的代碼了,由於確定是頁面中的業務代碼將請求推入到執行堆棧的,因此能夠在堆棧中找到對應的方法名:getVideoList

  4. 點擊方法名能夠跳轉到對應的源碼,能夠看到圈起來的代碼和所猜測的問題代碼應該是同一處

  5. 回過來看下問題緣由: 頁面請求完新數據後直接 pageNum 自增,而後直接就用因而否結束的判斷了,有點不夠嚴謹,不如直接比對當前的列表長度與接口返回的數據總數來判斷:

  6. 記住要修改的代碼,在這個文件開頭,也就是 191.xxx.js

    1. 第一行先打個斷點,push 方法以前再打一個斷點: (若是沒有再刷新一下 (也不清楚爲何可能會沒有))
    2. 而後刷新頁面,找到剛剛想要修改的代碼: 用 t.recommendList.length 替換掉 n.pageSize*t.pageNo(前兩步是爲了不 js 開始解析問題代碼,先阻塞一下運行: stackoverflow
  7. Ctrl + S,保存一下,而後看下頁面效果,列表能夠所有加載出來了:

在美化代碼的面板中是不支持直接修改頁面代碼的

黑盒模式

把腳本文件放入 Blackbox(黑盒),能夠忽略來自第三方庫的調用堆棧

默認(不開啓黑盒):

開啓黑盒:

  • 打開方式①

    1. 打開 DevTools Settings (設置)
    2. 在左側的導航菜單中,單擊 Blackboxing (黑箱)
    3. 點擊 Add pattern... (添加模式) 按鈕。
    4. Pattern(模式) 文本框輸入您但願從調用堆棧中排除的文件名模式。DevTools 會排除該模式匹配的任何腳本。
    5. 在文本字段右側的下拉菜單中,選擇 Blackbox (黑箱) 以執行腳本文件可是排除來自調用堆棧的調用,或選擇 Disabled (禁用) 來阻止文件執行。
    6. 點擊Add(添加) 保存
  • 打開方式②
    直接在想要忽略的堆棧信息上 blackbox script

DOM 斷點

查看 element 面板 DOM 斷點

Performance 面板

此章節請使用 Chrome 的隱身模式打開 /devtools/jank/index.html 一塊兒食用 隱身模式能夠保證 Chrome 在一個相對乾淨的環境下運行。假如安裝了許多 chrome 插件,這些插件可能會影響分析性能表現

在 Performance 面板能夠查看頁面加載過程當中的詳細信息,好比在什麼時間開始作什麼事情,耗時多久等等。相較於 Network 面板,不只能夠看到經過網絡加載資源的信息,還能看到解析 JS、計算樣式、重繪等頁面加載的方方面面的信息

面板主要的區域劃分:

  1. Controls - 開始記錄,中止記錄和配置記錄期間捕獲的信息

  2. Overview - 頁面性能的彙總

  3. Flame Chart - [火焰圖 (線程面板)]。在火焰圖上看到三條(綠色的有好幾條)垂直的虛線:

    • 藍線表明 DOMContentLoaded 事件
    • 綠線表明首次繪製的時間
    • 紅線表明 load 事件
  4. Details - 在 Flame Chart 中,選擇了某一事件後,這部分會展現與這個事件相關的更多信息;

    若是選擇了某一幀,這部分會展現與選中幀相關的信息。若是既沒有選中事件也沒有選中幀,則這部分會展現當前記錄時間段內的相關信息。

開始記錄

  1. 首先點擊控制條左邊的第一個圓圈,開始記錄日誌
  2. 等待幾分鐘 (正常操做頁面)
  3. 點擊 Stop 按鈕,Devtools 中止錄製,處理數據,而後顯示性能報告

而後就會出來上圖的內容

與臺式機和筆記本電腦相比移動設備的 CPU 功率要小得多。不管什麼時候分析頁面,都使用 CPU 限制來模擬頁面在移動設備上的表現。 在 "開發工具" 中,單擊 "性能" 選項卡。 確保啓用 "屏幕截圖" 複選框。 單擊 "捕獲設置"。 Capture SettingsDevTools 揭示了與如何捕獲性能指標相關的設置。 對於 CPU,選擇 2 倍減速。DevTools 會限制 CPU 使其速度比平時慢 2 倍

注意:若是想要確保它們在低端移動設備上運行良好,請將 CPU 限制設置爲 20 倍減速。

(1)controls 控制條區域

  • 上半區域
    • Screenshots 截圖:默認勾選,每一幀都會截圖
    • Memory 內存消耗記錄:勾選後能夠看到各類內存消耗曲線
  • 下面的 checkbox 區域
    • Disable javaScript samples [禁用 javaScript 示例]:減小在手機運行時系統的開銷,模擬手機運行時勾選
    • Network [網絡模擬]:能夠模擬在 3G,4G 等網絡條件下運行頁面
    • Enable advanced paint instrumentation(slow) [啓用高級畫圖檢測工具 (慢速)]:捕獲高級畫圖檢測工具,帶來顯著的性能開銷
    • CPU [CPU 限制性能]:主要爲了模擬底 CPU 下運行性能

(2)overview 總覽區域

FPS

綠色豎線越高,FPS 越高。 FPS 圖表上的紅色塊 (上圖剛開始的部分) 表示長時間幀,極可能會出現卡頓。常常打遊戲確定知道這個指標表明什麼,120FPS 表明流暢(手動滑稽)

火焰圖的 FPS 能夠量化這項參數

FPS(frames per second)是用來分析動畫的一個主要性能指標。能保持在 60 的 FPS 的話,那麼用戶體驗就是不錯的

Q: 爲何是 60fps?

A: 咱們的目標是保證頁面要有高於每秒 60fps(幀) 的刷新頻率,這和目前大多數顯示器的刷新率相吻合 (60Hz)。若是網頁動畫可以作到每秒 60 幀,就會跟顯示器同步刷新,達到最佳的視覺效果。這意味着,一秒以內進行 60 次從新渲染,每次從新渲染的時間不能超過 16.66 毫秒

CPU

CPU 資源。此面積圖指示消耗 CPU 資源的事件類型。在 CPU 圖表中的各類顏色與 Summary 面板裏的顏色是相互對應的,Summary 面板就在 Performance 面板的下方。CPU 圖表中的各類顏色表明着在這個時間段內,CPU 在各類處理上所花費的時間。若是你看到了某個處理佔用了大量的時間,那麼這可能就是一個能夠找到性能瓶頸的線索

CPU 資源面積圖顏色劃分:
顏色 執行內容
藍色 (Loading) 網絡通訊和 HTML 解析
黃色 (Scripting) JavaScript 執行
紫色 (Rendering) 樣式計算和佈局,即重排
綠色 (Painting) 更改外觀而不會影響佈局,重繪
灰色 (other) 其它事件花費的時間
白色 (Idle) 空閒時間

重繪是當節點須要更改外觀而不會影響佈局的,好比改變 color 就叫稱爲重繪 迴流 (重排) 是佈局或者幾何屬性須要改變就稱爲迴流

重排一定會發生重繪,重繪不必定會引起重排。重排所需的成本比重繪高的多,改變深層次的節點極可能致使父節點的一系列重排

js 修改 dom 結構或樣式 -> 計算 style -> layout(重排) -> paint(重繪) -> composite(合成)

性能優化的相關總結

NET

每條彩色橫槓表示一種資源。橫槓越長,檢索資源所需的時間越長。 每一個橫槓的淺色部分表示等待時間(從請求資源到第一個字節下載完成的時間) 深色部分表示傳輸時間(下載第一個和最後一個字節之間的時間)

  • HTML:藍色
  • CSS:紫色
  • JS:黃色
  • 圖片:綠色

感受優化網絡性能直接使用 network 面板就行了

(3)Flame Chart 火焰圖(線程面板)

詳細的分析某些任務的詳細耗時,從而定位問題

看到的幾條虛線:

  • 藍線表明 DOMContentLoaded 事件
  • 綠線表明首次繪製的時間
    • FP(First Paint): 首次繪製
    • FCP(First Contentful Paint): 第一次豐富內容的繪圖
    • FMP(First Meaningful Paint):第一次有意義的繪圖
    • LCP(Largest Contentful Paint): 最大區域內容繪製
  • 紅線表明 load 事件
  • DOMContentLoaded: 就是 dom 內容加載完畢。 那什麼是 dom 內容加載完畢呢?打開一個網頁當輸入一個 URL,頁面的展現首先是空白的,而後過一會,頁面會展現出內容,可是頁面的有些資源好比說圖片資源還沒法看到,此時頁面是能夠正常的交互,過一段時間後,圖片才完成顯示在頁面。從頁面空白到展現出頁面內容,會觸發 DOMContentLoaded 事件。而這段時間就是 HTML 文檔被加載和解析完成。

  • load: 頁面上全部的資源(圖片,音頻,視頻等)被加載之後纔會觸發 load 事件,簡單來講,頁面的 load 事件會在 DOMContentLoaded 被觸發以後才觸發。

Main

看下主線程,Devtools 展現了主線程運行情況

  • X 軸表明着時間。每一個長條表明着一個 event。長條越長就表明這個 event 花費的時間越長。
  • Y 軸表明了調用棧(call stack)。在棧裏,上面的 event 調用了下面的 event

Google 官方文檔的例子:

如上圖:click 事件觸發了 script_foot_closure.js 第 53 行的函數調用。 再看下面,Function Call 能夠看到一個匿名函數被調用,而後調用 Me() 函數,而後調用 Se(),依此類推。

DevTools 爲腳本分配隨機顏色。在上圖中,來自一個腳本的函數調用顯示爲淺綠色。來自另外一個腳本的調用被渲染成米色。較深的黃色表示腳本活動,而紫色的事件表示渲染活動。這些較暗的黃色和紫色事件在全部記錄中都是一致的。

  1. 在性能報告中,有不少的數據。能夠經過雙擊,拖動等等動做來放大縮小報告範圍,從各類時間段來觀察分析報告
  2. 在事件長條的右上角處,若是出現了紅色小三角,說明這個事件是存在問題的,須要特別注意
  3. 雙擊這個帶有紅色小三角的事件。在 Summary 面板會看到詳細信息。注意 reveal 這個連接,雙擊它會讓高亮觸發這個事件的 event。若是點擊了 app.js:94 這個連接,就會跳轉到對應的代碼處

(4)Details 區域

通常要配合 Flame Chart 一塊兒使用

  • Summary 區域是一個餅狀圖總覽,彙總了各個事件類型所耗費的總時長,另外還有三個查看選項:
  • Bottom-Up 選項卡:要查看直接花費最多時間的活動時使用
  • Call Tree 選項卡:想查看致使最多工做的根活動時使用
  • Event Log 選項卡:想要按記錄期間的活動順序查看活動時使用

window.performance 對象

Performance 接口能夠獲取到當前頁面中與性能相關的信息。它是 High Resolution Time API 的一部分,同時也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。

實質上來講 performance 對象就是專門用於性能監測的對象,內置了幾乎全部經常使用前端須要的性能參數監控

performance API

performance API

  • memory

    • totalJSHeapSize: '可以使用內存大小' // 單位 KB
    • usedJSHeapSize: '已使用內存大小'
    • jsHeapSizeLimit: '內存大小限制'
  • navigation

    • redirectCount: 0

      若是有重定向的話,頁面經過幾回重定向跳轉而來

    • type: 0

      相似於小程序定義的場景值,type 的值: 0 即 TYPE_NAVIGATENEXT 正常進入頁面(非刷新、非重定向等) 1 即 TYPE_RELOAD 經過 window.location.reload() 刷新的頁面 2 即 TYPE_BACK_FORWARD 經過瀏覽器的前進後退按鈕進入的頁面(歷史記錄) 255 即 TYPE_UNDEFINED 非以上方式進入的頁面

  • onresourcetimingbufferfull // 一個當 resourcetimingbufferfull 事件觸發時調用的 EventHandler 這個事件當瀏覽器的資源時間性能緩衝區已滿時會觸發

    // 在 onresourcetimingbufferfull 屬性上設置一個回調函數:
    function buffer_full(event) {
      console.log("WARNING: Resource Timing Buffer is FULL!");
      performance.setResourceTimingBufferSize(200);
    }
    function init() {
      // Set a callback if the resource buffer becomes filled
      performance.onresourcetimingbufferfull = buffer_full;
    }
    <body onload="init()">
    複製代碼
    複製代碼
  • timeOrigin: 1594219100175.9412

    返回性能測量開始時的時間的高精度時間戳

  • timing

    • navigationStart: '時間戳'

      在同一個瀏覽器上下文中,前一個網頁(與當前頁面不必定同域)unload 的時間戳,若是無前一個網頁 unload,則與 fetchStart 值相等;

    • unloadEventStart: 0

      前一個網頁(與當前頁面同域)unload 的時間戳,若是無前一個網頁 unload 或者前一個網頁與當前頁面不一樣域,則值爲 0

    • unloadEventEnd: 0

      和 unloadEventStart 相對應,返回前一個網頁 unload 事件綁定的回調函數執行王弼的時間戳

    • redirectStart: 0

      第一個 HTTP 重定向發生時的時間,有跳轉且是同域名內部的重定向纔算,不然值爲 0

    • redirectEnd: 0

      最後一個 HTTP 重定向完成時的時間,有跳轉切爾是同域名內部的重定向纔算,不然值爲 0

    • fetchStart: '時間戳'

      瀏覽器準備好使用 HTTP 請求抓取文檔的時間,這發生在檢查本地緩存以前

    • domainLookupStart: '時間戳'

      DNS 域名查詢開始的時間,若是使用了本地緩存(即無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等

    • domainLookupEnd: '時間戳'

      DNS 域名查詢完成的時間,若是使用了本地緩存(即 無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等

    • connectStart: '時間戳'

      HTTP(TCP) 開始創建鏈接的時間,若是是持久鏈接,則與 fetchStart 值相等;若是在傳輸層發生了錯誤且從新創建了鏈接,則這裏顯示的是新創建鏈接的時間

    • connectEnd: '時間戳'

      HTTP(TCP) 完成創建鏈接的時間(握手),若是是持久鏈接,則與 fetchStart 相等;若是是在傳輸層發生了錯誤且從新創建鏈接,則這裏咸寧市的是新創建的鏈接完成的時間;這

    • secureConnectionStart: 0

      HTTPS 鏈接開始的時間,若是不是安全鏈接,則值爲 0;

    • requestStart: '時間戳'

      HTTP 請求讀取真實文檔開始的時間(完成創建鏈接),包括從本地讀取緩存,鏈接錯誤時這裏顯示的是新創建的鏈接的時間

    • responseStart: '時間戳'

      HTTP 開始接收響應的時間(獲取到第一個字節),包括從本地讀取緩存

    • responseEnd: 0

      HTTP 響應所有接收完畢的時間(獲取到最後一個字節),包括從本地讀取的緩存

    • domLoading: 0

      開始解析渲染 DOM 樹的時間,此時 Document.readyState 變爲 interactive,並將拋出 readystatechange 相關事件(這裏只是 DOM 樹解析完畢,這時候並無開始加載網頁內的

    • dominteractive: 0

      完成解析 DOM 樹的時間,Document,readyState 變爲 interactive, 並將拋出 readystatechange 相關事件(這時候並無開始加載網頁資源)

    • domContentLoadedEventStart: 0

      DOM 解析完成後,網頁內資源加載開始的時間,在 DOMContentLoaded 事件拋出以前發生

    • domContentLoadedEventEnd: 0

      DOM 解析完成後,網頁內資源加載完成的時間

    • domComplete: 0

      DOM 樹解析完成,且資源也準備就緒的時間,Document.readyState 變爲 complete, 並將拋出 readystatechange 相關事件

    • loadEventStart: 0

      load 事件發送給文檔,也即 load 回調函數開始執行的時間,若是沒有綁定 load 事件,值爲 0

    • loadEventEnd: 0

      load 事件的回調函數執行完畢的時間

幾個實用的 API

performance.now() 方法

performance.now() 返回 performance.navigationStart 至當前的毫秒數。 performance.navigationStart 是下文將介紹到的能夠說是瀏覽器訪問最初的時間測量點。

值得注意的兩點:

  • 測量初始點是瀏覽器訪問最初測量點,或者理解爲在地址欄輸入 URL 後按回車的那一瞬間。
  • 返回值是毫秒數,但帶有精準的多位小數。

用 performance.now() 檢測 js 代碼的執行時間 (毫秒):

var st = performance.now();
  console.log(Array(9999999).fill(null).filter(v => !v).length);
  var end = performance.now();
  console.log(`取值時間${end - st}ms`); // 取值時間 558.7849999992759ms
複製代碼
複製代碼

performance.navigation

performance.navigation 負責紀錄用戶行爲信息,只有兩個屬性:

  • redirectCount
    • 若是有重定向的話,頁面經過幾回重定向跳轉而來
  • type
    • type 的值:
    • 0 即 TYPE_NAVIGATENEXT 正常進入頁面(非刷新、非重定向等)
    • 1 即 TYPE_RELOAD 經過 window.location.reload() 刷新的頁面
    • 2 即 TYPE_BACK_FORWARD 經過瀏覽器的前進後退按鈕進入的頁面(歷史記錄)
    • 255 即 TYPE_UNDEFINED 非以上方式進入的頁面
console.log(performance.navigation); // PerformanceNavigation {type: 1, redirectCount: 0}
複製代碼
複製代碼
performance.timing

timing 內包含了幾乎全部時序的時間節點

能夠經過此字段來統計頁面相關事件的發生時長:

function getTiming() {
  try {
    var timing = performance.timing;
    var timingObj = {};

    var loadTime = (timing.loadEventEnd - timing.loadEventStart) / 1000;

    if(loadTime < 0) {
      setTimeout(function() {
        getTiming();
      }, 0);
      return;
    }

    timingObj['重定向時間'] = (timing.redirectEnd - timing.redirectStart);
    timingObj['DNS 解析時間'] = (timing.domainLookupEnd - timing.domainLookupStart);
    timingObj['TCP 完成握手時間'] = (timing.connectEnd - timing.connectStart);
    timingObj['HTTP 請求響應完成時間'] = (timing.responseEnd - timing.requestStart);
    timingObj['DOM 開始加載前所花費時間'] = (timing.responseEnd - timing.navigationStart);
    timingObj['DOM 加載完成時間'] = ((timing.domComplete || timing.domLoading) - timing.domLoading);
    timingObj['DOM 結構解析完成時間'] = (timing.domInteractive - timing.domLoading);
    timingObj['整體網絡交互耗時,即開始跳轉到服務器資源下載完成時間'] = (timing.responseEnd - timing.navigationStart);
    timingObj['可交互的時間'] = (timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart);
    timingObj['首次出現內容'] = (timing.domLoading - timing.navigationStart);
    timingObj['onload 事件時間'] = (timing.loadEventEnd - timing.loadEventStart);
    timingObj['頁面徹底加載時間'] = (timingObj['重定向時間'] + timingObj['DNS 解析時間'] + timingObj['TCP 完成握手時間'] + timingObj['HTTP 請求響應完成時間'] + timingObj['DOM 結構解析完成時間'] + timingObj['DOM 加載完成時間']);

    for(item in timingObj) {
      console.log(item + ":" + timingObj[item] + '(ms)');
    }

    console.log(performance.timing);

  } catch(e) {
    console.log(performance.timing);
  }
}
window.onload = getTiming
複製代碼
複製代碼
performance.memory

用於顯示當前的內存佔用狀況

console.log(performance.memory)
/* {
  jsHeapSizeLimit: 4294705152,
  totalJSHeapSize: 13841857,
  usedJSHeapSize: 12417637
} */
複製代碼
複製代碼
  • usedJSHeapSize 表示:JS 對象(包括 V8 引擎內部對象)佔用的內存數
  • totalJSHeapSize 表示:可以使用的內存
  • jsHeapSizeLimit 表示:內存大小限制

一般,usedJSHeapSize 不能大於 totalJSHeapSize,若是大於,有可能出現了內存泄漏。

performance.getEntries()

瀏覽器獲取網頁時,會對網頁中每個對象(腳本文件、樣式表、圖片文件等等)發出一個 HTTP 請求。performance.getEntries 方法以數組形式,返回一個 PerformanceEntry 列表,這些請求的時間統計信息,有多少個請求,返回數組就會有多少個成員

  • name:資源的連接
  • duration: 資源的總耗時(包括等待時長,請求時長,響應時長 至關於 responseEnd - startTime)
  • entryType: 資源類型,entryType 類型不一樣數組中的對象結構也不一樣:
    該類型對象 描述
    mark PerformanceMark 經過 mark() 方法添加到數組中的對象
    measure PerformanceMeasure 經過 measure() 方法添加到數組中的對象
    paint PerformancePaintTiming 值爲 first-paint'首次繪製、'first-contentful-paint'首次內容繪製。
    resource PerformanceResourceTiming 全部資源加載時間,用處最多
    navigation PerformanceNavigationTiming 現除 chrome 和 Opera 外均不支持,導航相關信息
    frame PerformanceFrameTiming 現瀏覽器均未支持
  • initiatorType: 如何發起的請求, 初始類型(注意這個類型並不許確,例如在 css 中的圖片資源會這個值顯示 css,因此仍是推薦用 name 中的後綴名)
    發起對象 描述
    a Element link/script/img/iframe 等 經過標籤形式加載的資源,值是該節點名的小寫形式
    a CSS resource css 經過 css 樣式加載的資源,好比 background 的 url 方式加載資源
    a XMLHttpRequest object xmlhttprequest/fetch 經過 xhr 加載的資源
    a PerformanceNavigationTiming object navigation 當對象是 PerformanceNavigationTiming 時返回
performance.getEntriesByType()

方法返回給定類型的 getEntries 列表 打開頁面

這段代碼能夠在 DevTools 控制檯中運行。它將使用Resource Timing API(資源時序 API) 來檢索全部資源。而後它過濾條目,查找包含logo-1024px.png名稱的條目。若是找到,會返回相關信息。

performance
  .getEntriesByType('resource')
  .filter(item => item.name.includes('logo-1024px.png'))
複製代碼
複製代碼

注意:
返回資源的 connectEnd 等相關字段不是 Unix 時間戳,而是 DOMHighResTimeStampMDN PerformanceResourceTiming

DOMHighResTimeStamp 是一個 double 類型,用於存儲時間值。該值能夠是離散的時間點或兩個離散時間點之間的時間差。T 單位爲毫秒 ms (milliseconds) ,應準確至 5 微秒 µs (microseconds)。可是,若是瀏覽器沒法提供準確到 5 微秒的時間值 (例如, 因爲硬件或軟件的限制), 瀏覽器能夠以毫秒爲單位的精確到毫秒的時間表示該值

Lighthouse(Audits) 面板

來自 Google 的描述: Lighthouse 是一個開源的自動化工具,用於改進網絡應用的質量。 您能夠將其做爲一個 Chrome 擴展程序運行,或從命令行運行。 您爲 Lighthouse 提供一個您要審查的網址,它將針對此頁面運行一連串的測試,而後生成一個有關頁面性能的報告

會對頁面的加載進行分析,而後給出提升頁面性能的建議

懶人專用👍

有 5 個指標:

  • Performance 性能
  • accessibility 無障礙使用
  • Best Practice 用戶體驗
  • SEO SEO 優化
  • Progressive Web App 頁對於 PWA 的兼容性

Security 面板

用於檢測當面頁面的安全性

該面板能夠區分兩種類型的不安全的頁面:

  • 若是被請求的頁面經過 HTTP 提供服務,那麼這個主源就會被標記爲不安全。
  • 若是被請求的頁面是經過 HTTPS 獲取的,但這個頁面接着經過 HTTP 繼續從其餘來源檢索內容,那麼這個頁面仍然被標記爲不安全。這就是所謂的混合內容頁面, 混合內容頁面只是部分受到保護, 由於 HTTP 內容 (非加密的內容通訊使用明文) 可能會被竊聽, 容易受到中間人攻擊。如 163,雖然證書是有效的,可是頁面有一部分 http 資源:

Command 終極大招

在控制檯打開的狀態下, 組合按鍵 Ctrl + Shift + P / Command + Shift + P 打開 「命令」 菜單,接下來就能夠隨心所欲了~

截圖

當你只想對一個特定的 DOM 節點進行截圖時,可能須要使用其餘工具操做很久,使用控制檯能夠直接選中想要截圖的節點,打開 Command 菜單而且使用 節點截圖 就能夠了

  • 截取特定節點: Screenshot Capture node screenshot
  • 全屏截圖: Screenshot Capture full size screenshot

CSS/JS 覆蓋率

媒體查詢

媒體查詢是自適應網頁設計的基本部分。 在 Chrome Devtools 中的設備模式下,在三圓點菜單點擊, Show Media queries 便可啓用:

右鍵點擊某個條形,查看媒體查詢在 CSS 中何處定義並跳到源代碼中的定義

參考

相關文章
相關標籤/搜索