導航和資源計時
導航計時是衡量瀏覽器文件導航事件的指標。資源計時是關於應用程式資源載入的詳細網路計時測量。兩者都提供相同的只讀屬性,但導航計時測量主文件的計時,而資源計時提供所有由該主文件呼叫的資產或資源以及資源請求的資源的計時。
以下常規效能計時已被棄用,取而代之的是效能條目 API,它可以用於標記和測量導航和資源載入過程中的時間。儘管已棄用,但它們在所有瀏覽器中都受支援。
效能計時
用於測量請求頁面的載入效能的performanceTiming API已棄用,但在所有瀏覽器中都受支援。它已被performanceNavigationTiming API 替代。
效能計時 API 以毫秒 (ms) 為單位提供只讀時間,描述在頁面載入過程中的每個點何時到達。如下面的影像所示,導航過程從navigationStart、unloadEventStart、unloadEventEnd、redirectStart、redirectEnd、fetchStart、domainLookupStart、domainLookupEnd、connectStart、connectEnd、secureConnectionStart、requestStart、responseStart、responseEnd、domLoading、domInteractive、domContentLoadedEventStart、domContentLoadedEventEnd、domComplete、loadEventStart 和loadEventEnd。
使用上述指標和一些數學運算,我們可以計算許多重要的指標,例如首位元組時間、頁面載入時間、DNS 查詢以及連線是否安全。
為了幫助測量完成所有步驟所需的時間,Performance Timing API 提供了導航計時的只讀測量。要檢視和捕獲我們應用程式的計時,我們輸入
let time = window.performance.timing;
然後我們可以使用結果來衡量我們的應用程式的效能。
順序為
| 效能計時 | 細節 |
|---|---|
navigationStart |
當對先前文件(在同一瀏覽上下文中)的解除安裝提示終止時。如果沒有先前的文件,則此值將與PerformanceTiming.fetchStart相同。 |
secureConnectionStart |
當安全連線握手開始時。如果沒有請求此類連線,則返回0。 |
redirectStart |
當第一個 HTTP 重定向開始時。如果沒有重定向,或者重定向之一不是同一來源,則返回的值為0。 |
redirectEnd |
當最後一個 HTTP 重定向完成時,即當接收到 HTTP 響應的最後一個位元組時。如果沒有重定向,或者重定向之一不是同一來源,則返回的值為 |
connectEnd |
當連線開啟網路時。如果傳輸層報告錯誤並且連線建立重新開始,則給出最後一次連線建立結束時間。如果使用持久連線,則該值將與PerformanceTiming.fetchStart相同。當所有安全連線握手或 SOCKS 身份驗證終止時,連線被視為已開啟。 |
connectStart |
當向網路傳送開啟連線的請求時。如果傳輸層報告錯誤並且連線建立重新開始,則給出最後一次連線建立開始時間。如果使用持久連線,則該值將與PerformanceTiming.fetchStart相同。 |
domainLookupEnd |
當域名查詢完成時。如果使用持久連線,或者資訊儲存在快取或本地資源中,則該值將與PerformanceTiming.fetchStart相同。 |
domainLookupStart |
當域名查詢開始時。如果使用持久連線,或者資訊儲存在快取或本地資源中,則該值將與PerformanceTiming.fetchStart相同。 |
fetchStart |
當瀏覽器準備好使用 HTTP 請求獲取文件時。此時刻在檢查任何應用程式快取之前。 |
requestStart |
當瀏覽器傳送請求以從伺服器或快取中獲取實際文件時。如果傳輸層在請求開始後失敗並且連線重新開啟,則此屬性將設定為對應於新請求的時間。 |
responseStart |
當瀏覽器從伺服器、快取或本地資源接收到響應的第一個位元組時。 |
responseEnd |
當瀏覽器接收到響應的最後一個位元組時,或者如果連線先關閉,則從伺服器、快取或本地資源接收到響應的最後一個位元組時。 |
domLoading |
當解析器開始工作時,即其Document.readyState更改為'loading'並且丟擲相應的readystatechange事件時。 |
unloadEventStart |
當丟擲unload事件時,指示視窗中先前文件開始解除安裝的時間。如果沒有先前的文件,或者先前的文件或所需重定向之一不是同一來源,則返回的值為0。 |
unloadEventEnd |
當unload事件處理程式完成時。如果沒有先前的文件,或者先前的文件或所需重定向之一不是同一來源,則返回的值為0。 |
domInteractive |
當解析器完成對主文件的工作時,即其Document.readyState更改為'interactive'並且丟擲相應的readystatechange事件時。 |
domContentLoadedEventStart |
在解析器傳送DOMContentLoaded事件之前,即在解析後需要執行的所有指令碼都已執行之後。 |
domContentLoadedEventEnd |
在所有需要儘快執行的指令碼(無論順序如何)都已執行之後。 |
domComplete |
當解析器完成對主文件的工作時,即其Document.readyState更改為'complete'並且丟擲相應的readystatechange事件時。 |
loadEventStart |
當為當前文件傳送load事件時。如果尚未傳送此事件,則返回0.。 |
loadEventEnd |
當load事件處理程式終止時,即載入事件完成時。如果尚未傳送此事件或尚未完成,則返回0.。 |
計算計時
我們可以使用這些值來衡量感興趣的特定計時
const dns = time.domainLookupEnd - time.domainLookupStart;
const tcp = time.connectEnd - time.connectStart;
const tls = time.requestStart - time.secureConnectionStart;
首位元組時間
首位元組時間是在navigationStart(導航開始)和responseStart(接收到響應資料的第一個位元組時)之間的時間,在performanceTiming API 中可用
const ttfb = time.responseStart - time.navigationStart;
頁面載入時間
頁面載入時間是在navigationStart和為當前文件傳送載入事件的開始之間的時間。它們僅在 performanceTiming API 中可用。
let pageloadtime = time.loadEventStart - time.navigationStart;
DNS 查詢時間
DNS 查詢時間是在domainLookupStart和domainLookupEnd之間的時間。這些都可以在performanceTiming和performanceNavigationTiming API 中使用。
const dns = time.domainLookupEnd - time.domainLookupStart;
TCP
完成TCP握手所需的時間是在連線開始和連線結束之間的時間
const tcp = time.connectEnd - time.connectStart;
TLS 協商
secureConnectionStart如果不可用則為undefined,如果未使用HTTPS則為0,或者如果可用且已使用則為時間戳。換句話說,如果使用了安全連線,則secureConnectionStart將為真值,並且secureConnectionStart和requestStart之間的時間將大於 0。
const tls = time.requestStart - time.secureConnectionStart;
效能條目 API
上述一般效能計時已棄用,但完全受支援。我們現在有了效能條目 API,它可以用於標記和測量導航和資源載入過程中的時間。您還可以建立標記
performance.getEntriesByType("navigation").forEach((navigation) => {
console.dir(navigation);
});
performance.getEntriesByType("resource").forEach((resource) => {
console.dir(resource);
});
performance.getEntriesByType("mark").forEach((mark) => {
console.dir(mark);
});
performance.getEntriesByType("measure").forEach((measure) => {
console.dir(measure);
});
performance.getEntriesByType("paint").forEach((paint) => {
console.dir(paint);
});
performance.getEntriesByType("frame").forEach((frame) => {
console.dir(frame);
});
在支援的瀏覽器中,您可以使用performance.getEntriesByType('paint')查詢first-paint和first-contentful-paint的測量結果。我們使用performance.getEntriesByType('navigation')和performance.getEntriesByType('resource')分別查詢導航和資源的計時資訊。
導航計時
當用戶請求一個網站或應用程式時,為了填充瀏覽器,使用者代理會經歷一系列步驟,包括DNS查詢、TCP握手和TLS協商,然後使用者代理才會發出實際請求,伺服器返回請求的資源。瀏覽器隨後解析接收到的內容,構建DOM、CSSOM、可訪問性和渲染樹,最終渲染頁面。一旦使用者代理停止解析文件,使用者代理就會將文件就緒狀態設定為interactive。如果存在需要解析的延遲指令碼,它將執行解析,然後觸發DOMContentLoaded事件,之後就緒狀態將設定為complete。文件現在可以處理載入後的任務,在此之後,文件被標記為完全載入。
const navigationTimings = performance.getEntriesByType("navigation");
performance.getEntriesByType('navigation')返回一個包含navigation型別的PerformanceEntry物件的陣列。
從這些計時資訊中可以獲得很多有用的資訊。在上圖中,我們透過name屬性可以看到正在計時的檔案是當前文件。在接下來的解釋中,我們使用以下變數
const timing = performance.getEntriesByType("navigation")[0];
協議
我們可以透過查詢來檢查使用的協議
const protocol = timing.nextHopProtocol;
它返回用於獲取資源的網路協議:在本例中,h2表示http/2。
壓縮
要獲取壓縮節省的百分比,我們將transferSize除以decodedBodySize,然後從100%中減去結果。我們看到節省了超過74%。
const compressionSavings = 1 - timing.transferSize / timing.decodedBodySize;
我們本可以使用
const compressionSavings = 1 - timing.encodedBodySize / timing.decodedBodySize;
但使用transferSize包含了開銷位元組。
為了比較,我們可以檢視網路選項卡,發現我們傳輸了22.04KB,未壓縮的檔案大小為87.24KB。
如果我們用這些數字進行計算,會得到相同的結果:1 - (22.04 / 87.24) = 0.747。導航計時為我們提供了一種以程式設計方式檢查傳輸大小和頻寬節省的方法。
請注意,這是單個文件的大小:僅針對此資源,不包括所有資源的總和。但是,持續時間、載入事件和與DOM相關的計時與整個導航有關,而不是單個資源。客戶端Web應用程式可能看起來比此應用程式快,傳輸大小低於10000,解碼正文大小低於30000,但這並不意味著JavaScript、CSS或媒體資源沒有增加冗餘。檢查壓縮率很重要,但也要檢查持續時間以及DOMContentLoaded事件結束到DOM完成之間的時間,因為在主執行緒上長時間執行JavaScript會導致使用者介面無響應。
請求時間
API沒有提供您可能希望的每個測量值。例如,請求花費了多長時間?我們可以使用我們擁有的測量值來獲得答案。
要測量響應時間,請從響應開始時間減去請求開始時間。請求開始是使用者代理開始從伺服器或相關應用程式快取或本地資源請求資源之前的時刻。響應開始是使用者代理的HTTP解析器從相關應用程式快取或本地資源或伺服器接收響應的第一個位元組之後的時刻,這發生在接收和處理請求之後。
const request = timing.responseStart - timing.requestStart;
載入事件持續時間
透過從當前文件的載入事件完成時的時間減去當前文件的載入事件觸發之前的時刻的時間戳,可以測量載入事件的持續時間。
const load = timing.loadEventEnd - timing.loadEventStart;
DOMContentLoaded事件
DOMContentLoaded事件持續時間透過從使用者代理觸發DOMContentLoaded事件後的時刻的時間值減去觸發DOMContentLoaded事件之前的時刻的時間值來測量。將此時間保持在50毫秒或更短有助於確保使用者介面響應迅速。
const DOMContentLoaded =
timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart;
持續時間
我們獲得了持續時間。持續時間是PerformanceNavigationTiming.loadEventEnd和PerformanceEntry.startTime屬性之間的差值。
PerformanceNavigationTiming介面還提供有關正在測量的導航型別的資訊,返回navigate、reload、back_forward或prerender。
資源計時
導航計時用於測量主頁面(通常是請求所有其他資源的HTML檔案)的效能,而資源計時則用於測量單個資源(主頁面呼叫的資源以及這些資源請求的任何資源)的計時。許多測量值是相似的:每個域名都會執行一次DNS查詢、TCP握手和安全連線啟動。
每個資源的主要關注點。