日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

前端白屏问题_深入理解前端性能监控

發(fā)布時間:2025/3/12 HTML 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端白屏问题_深入理解前端性能监控 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在同樣的網(wǎng)絡(luò)環(huán)境下,有兩個同樣能滿足你的需求的網(wǎng)站,一個唰的一下就加載出來了,另一個白屏轉(zhuǎn)圈轉(zhuǎn)了半天內(nèi)容才出來,如果讓你選擇,你會用哪一個?

頁面的性能問題是前端開發(fā)中一個重要環(huán)節(jié),但一直以來我們沒有比較好的手段,來檢測頁面的性能。直到W3C性能小組引入的新的API window.performance,目前IE9以上的瀏覽器都支持。

它是一個瀏覽器中用于記錄頁面加載和解析過程中關(guān)鍵時間點(diǎn)的對象。放置在global環(huán)境下,通過JavaScript可以訪問到它。

使用性能API

你可以通過以下方法來探測和兼容performance:

var performance = window.performance ||
window.msPerformance ||
window.webkitPerformance;
if (performance) {
// 你的代碼
}

先來了解一下performance的結(jié)構(gòu):

performance.memory是顯示此刻內(nèi)存占用情況,它是一個動態(tài)值,其中:

usedJSHeapSize表示:JS 對象(包括V8引擎內(nèi)部對象)占用的內(nèi)存數(shù)

totalJSHeapSize表示:可使用的內(nèi)存?

jsHeapSizeLimit表示:內(nèi)存大小限制 通常,usedJSHeapSize不能大于totalJSHeapSize,如果大于,有可能出現(xiàn)了內(nèi)存泄漏。

performance.navigation顯示頁面的來源信息,其中: redirectCount表示:如果有重定向的話,頁面通過幾次重定向跳轉(zhuǎn)而來。

默認(rèn)為0 type表示頁面打開的方式, 0 表示 TYPE_NAVIGATENEXT 正常進(jìn)入的頁面(非刷新、非重定向等)。

1 表示 TYPE_RELOAD 通過? ? ? ? ? ? ?window.location.reload() 刷新的頁面。

2 表示 TYPE_BACK_FORWARD 通過瀏覽器的前進(jìn)后退按鈕進(jìn)入的頁面(歷史記錄) 。

255 表示 TYPE_UNDEFINED 非以上方式進(jìn)入的頁面。

performance.onresourcetimingbufferfull?屬性是一個在resourcetimingbufferfull事件觸發(fā)時會被調(diào)用的 event handler 。它的值是一個手動設(shè)置的回調(diào)函數(shù),這個回調(diào)函數(shù)會在瀏覽器的資源時間性能緩沖區(qū)滿時執(zhí)行。

performance.timeOrigin是一系列時間點(diǎn)的基準(zhǔn)點(diǎn),精確到萬分之一毫秒。

performance.timing是一系列關(guān)鍵時間點(diǎn),它包含了網(wǎng)絡(luò)、解析等一系列的時間數(shù)據(jù)。

下面是對這些時間點(diǎn)進(jìn)行解釋

timing: {
// 同一個瀏覽器上一個頁面卸載(unload)結(jié)束時的時間戳。如果沒有上一個頁面,這個值會和fetchStart相同。
navigationStart: 1543806782096,
// 上一個頁面unload事件拋出時的時間戳。如果沒有上一個頁面,這個值會返回0。
unloadEventStart: 1543806782523,

// 和 unloadEventStart 相對應(yīng),unload事件處理完成時的時間戳。如果沒有上一個頁面,這個值會返回0。
unloadEventEnd: 1543806782523,

// 第一個HTTP重定向開始時的時間戳。如果沒有重定向,或者重定向中的一個不同源,這個值會返回0。
redirectStart: 0,

// 最后一個HTTP重定向完成時(也就是說是HTTP響應(yīng)的最后一個比特直接被收到的時間)的時間戳。
// 如果沒有重定向,或者重定向中的一個不同源,這個值會返回0.
redirectEnd: 0,

// 瀏覽器準(zhǔn)備好使用HTTP請求來獲取(fetch)文檔的時間戳。這個時間點(diǎn)會在檢查任何應(yīng)用緩存之前。
fetchStart: 1543806782096,

// DNS 域名查詢開始的UNIX時間戳。
//如果使用了持續(xù)連接(persistent connection),或者這個信息存儲到了緩存或者本地資源上,這個值將和fetchStart一致。
domainLookupStart: 1543806782096,

還有一些其他的參數(shù)就不一一列舉了,這些參數(shù)非常有用,可以幫助我們獲取頁面的Domready時間、onload時間、白屏?xí)r間等,以及單個頁面資源在從發(fā)送請求到獲取到rsponse各階段的性能參數(shù)。

對我們比較有用的頁面性能數(shù)據(jù)大概包括如下幾個,這些參數(shù)是通過上面的? ? ? ? ? ? ? ? ? performance.timing各個屬性的差值組成的,它是精確到毫秒的一個值,計(jì)算方法如下:

  • 重定向耗時 : redirectEnd - redirectStart

  • DNS查詢耗時?:?domainLookupEnd - domainLookupStart

  • TCP鏈接耗時 :?connectEnd - connectStart

  • HTTP請求耗時 :?responseEnd - responseStart

  • 解析dom樹耗時?: domComplete - domInteractive

  • 白屏?xí)r間 :?responseStart - navigationStart

  • DOMready時間 :

    ?domContentLoadedEventEnd - navigationStart

  • onload時間:loadEventEnd - navigationStart,也即是onload回調(diào)函數(shù)執(zhí)行的時間。

如何優(yōu)化?

是隱式的 DNS Prefetch。如果想對頁面中沒有出現(xiàn)的域進(jìn)行預(yù)獲取,那么就要使用顯示的 DNS Prefetch 了。下圖是DNS Prefetch的方法:



騰訊網(wǎng)
"dns-prefetch" href="//mat1.gtimg.com" />
"dns-prefetch" href="//inews.gtimg.com" />
"dns-prefetch" href="//wx.qlogo.cn" />
"dns-prefetch" href="//coral.qq.com" />
"dns-prefetch" href="//pingjs.qq.com" />

**TCP請求優(yōu)化**:TCP的優(yōu)化大都在服務(wù)器端,前端能做的就是盡量減少TCP的請求數(shù),也就是減少HTTP的請求數(shù)量。http 1.0 默認(rèn)使用短連接,也是TCP的短連接,也就是客戶端和服務(wù)端每進(jìn)行一次http操作,就建立一次連接,任務(wù)結(jié)束就中斷連接。

這個過程中有3次TCP請求握手和4次TCP請求釋放。減少TCP請求的方式有兩種,一種是資源合并,對于頁面內(nèi)的圖片、css和js進(jìn)行合并,減少請求量。

另一種使用長鏈接,使用http1.1,在HTTP的響應(yīng)頭會加上 Connection:keep-alive,當(dāng)一個網(wǎng)頁打開完成之后,連接不會馬上關(guān)閉,再次訪問這個服務(wù)時,會繼續(xù)使用這個長連接。

這樣就大大減少了TCP的握手次數(shù)和釋放次數(shù)。或者使用Websocket進(jìn)行通信,全程只需要建立一次TCP鏈接。

**HTTP請求優(yōu)化**:使用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)和減少請求。使用CDN可以減少網(wǎng)絡(luò)的請求時延,CDN的域名不要和主站的域名一樣,這樣會防止訪問CDN時還攜帶主站cookie的問題,對于網(wǎng)絡(luò)請求,可以使用fetch發(fā)送無cookie的請求,減少http包的大小。也可以使用本地緩存策略,盡量減少對服務(wù)器數(shù)據(jù)的重復(fù)獲取。

**渲染優(yōu)化**:在瀏覽器端的渲染過程,如大型框架,vue和react,它的模板其實(shí)都是在瀏覽器端進(jìn)行渲染的,不是直出的html,而是要走框架中相關(guān)的框架代碼才能去渲染出頁面,這個渲染過程對于首屏就有較大的損耗,白屏的時間會有所增加。在必要的情況下可以在服務(wù)端進(jìn)行整個html的渲染,從而將整個html直出到我們的瀏覽器端,而非在瀏覽器端進(jìn)行渲染。

還有一個問題就是,在默認(rèn)情況下,JavaScript 執(zhí)行會“阻止解析器”,當(dāng)瀏覽器遇到一個 script 外鏈標(biāo)記時,DOM 構(gòu)建將暫停,會將控制權(quán)移交給 JavaScript 運(yùn)行時,等腳本下載執(zhí)行完畢,然后再繼續(xù)構(gòu)建 DOM。而且內(nèi)聯(lián)腳本始終會阻止解析器,除非編寫額外代碼來推遲它們的執(zhí)行。

我們可以把 script 外鏈加入到頁面底部,也可以使用 defer 或 async 延遲執(zhí)行。defer 和 async 的區(qū)別就是 defer 是有序的,代碼的執(zhí)行按在html中的先后順序,而 async 是無序的,只要下載完畢就會立即執(zhí)行。或者使用異步的編程方法,比如settimeout,也可以使用多線webworker,它們不會阻礙 DOM 的渲染。



資源性能API

performance.timing記錄的是用于分析頁面整體性能指標(biāo)。如果要獲取個別資源(例如JS、圖片)的性能指標(biāo),就需要使用Resource Timing API。 **performance.getEntries()**方法,包含了所有靜態(tài)資源的數(shù)組列表;每一項(xiàng)是一個請求的相關(guān)參數(shù)有name,type,時間等等。下圖是chrome顯示騰訊網(wǎng)的相關(guān)資源列表。

可以看到,與 performance.timing 對比: 沒有與 DOM 相關(guān)的屬性,新增了name、entryType、initiatorType和duration四個屬性。它們是

  • name表示:?資源名稱,也是資源的絕對路徑,可以通過? ? ? ? ? ?performance.getEntriesByName(name屬性的值),來獲取這個資源加載的具體屬性。

  • entryType表示:資源類型 "resource",還有“navigation”, “mark”, 和 “measure”另外3種。

  • initiatorType表示:請求來源"link",即表示標(biāo)簽還有? ? ? ? ? ? script即?,“img”即標(biāo)簽,“css”比如background的url方式加載資源以及“redirect”即重定向 等。

  • duration表示:加載時間,是一個毫秒數(shù)字。 受同源策略影響,跨域資源獲取到的時間點(diǎn),通常為0,如果需要更詳細(xì)準(zhǔn)確的時間點(diǎn),可以單獨(dú)請求資源通過performance.timing獲得。或者資源服務(wù)器開啟響應(yīng)頭Timing-Allow-Origin,添加指定來源站點(diǎn),如下所示:

Timing-Allow-Origin: https://qq.com

方法集合

除了performance.getEntries之? ? ? ? ? ? ?外,performance還包含一系列有用的方法。如下圖

performance.now()??返回一個當(dāng)前頁面執(zhí)行的時間的時間戳,用來精確計(jì)算程序執(zhí)行時間。與?Date.now()?不同的是,它使用了一個浮點(diǎn)數(shù),返回了以毫秒為單位,小數(shù)點(diǎn)精確到微秒級別的時間,更加精準(zhǔn)。并且不會受系統(tǒng)程序執(zhí)行阻塞的影響,performance.now()?的時間是以恒定速率遞增的,不受系統(tǒng)時間的影響(系統(tǒng)時間可被人為或軟件調(diào)整)。performance.timing.navigationStart + performance.now()?約等于?Date.now()。

let t0 = window.performance.now();
doSomething();
let t1 = window.performance.now();
console.log("doSomething函數(shù)執(zhí)行了" + (t1 - t0) + "毫秒.")

通過這個方法,我們可以用來測試某一段代碼執(zhí)行了多少時間。

performance.mark()?mark方法用來自定義添加標(biāo)記時間。使用方法如下:

var nameStart = 'markStart';
var nameEnd = 'markEnd';
// 函數(shù)執(zhí)行前做個標(biāo)記
window.performance.mark(nameStart);
for (var i = 0; i < n; i++) {
doSomething
}
// 函數(shù)執(zhí)行后再做個標(biāo)記
window.performance.mark(nameEnd);
// 然后測量這個兩個標(biāo)記間的時間距離,并保存起來
var name = 'myMeasure';
window.performance.measure(name, nameStart, nameEnd);

保存后的值可以通過?** performance.getEntriesByname( 'myMeasure' )**或者?performance.getEntriesByType('measure')查詢。

Performance.clearMeasures()?從瀏覽器的性能輸入緩沖區(qū)中移除自定義添加的 measure

Performance.getEntriesByName()?返回一個 PerformanceEntry 對象的列表,基于給定的 name 和 entry type

Performance.getEntriesByType()?返回一個 PerformanceEntry 對象的列表,基于給定的 entry type

Performance.measure()?在瀏覽器的指定 start mark 和 end mark 間的性能輸入緩沖區(qū)中創(chuàng)建一個指定名稱的時間戳,見上例

Performance.toJSON()?是一個 JSON 格式轉(zhuǎn)化器,返回 Performance 對象的 JSON 對象

資源緩沖區(qū)監(jiān)控

Performance.setResourceTimingBufferSize()?設(shè)置當(dāng)前頁面可緩存的最大資源數(shù)據(jù)個數(shù),entryType為resource的資源數(shù)據(jù)個數(shù)。超出時,會清空所有entryType為resource的資源數(shù)據(jù)。參數(shù)為整數(shù)(maxSize)。

配合performance.onresourcetimingbufferfull事件可以有效監(jiān)控資源緩沖區(qū)。當(dāng)entryType為resource的資源數(shù)量超出設(shè)置值的時候會觸發(fā)該事件。

Performance.clearResourceTimings()?從瀏覽器的性能數(shù)據(jù)緩沖區(qū)中移除所有的 entryType 是 "resource" 的 performance entries 下面是mdn上關(guān)于這個屬性的一個demo。這個demo的主要內(nèi)容是當(dāng)緩沖區(qū)內(nèi)容滿時,調(diào)用buffer_full函數(shù)。

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;
}
"init()">

使用performance的這些屬性和方法,能夠準(zhǔn)確的記錄下我們想要的時間,再加上日志采集等功能的輔助,我們就能很容易的掌握自己網(wǎng)站的各項(xiàng)性能指標(biāo)了。

兼容性

目前主流瀏覽器雖然都已支持performance對象,但是并不能支持它上面的全部屬性和方法,有些細(xì)微的差別。本文主要依據(jù)chrome和qq瀏覽器測試了相關(guān)屬性和方法,均可使用。

我們做了什么?(劃重點(diǎn))

現(xiàn)在的很多性能監(jiān)控分析工具都是通過數(shù)據(jù)上報來實(shí)現(xiàn)的,不能及時有效的反饋頁面的性能問題,只能在用戶使用之后上報(問題出現(xiàn)之后)才能知道。所以基于新聞前端團(tuán)隊(duì)基于performance API做了一款實(shí)時查看性能的的工具,它并能給出詳細(xì)的報表,在開發(fā)階段把性能問題給解決掉。

superProfiler**【外部開源流程中】**

它是一款JavaScript性能監(jiān)控工具庫,通過腳本引用,加載展示在頁面右側(cè),無須依賴任何庫和腳本,可以實(shí)時查看當(dāng)前頁面的FPS、代碼執(zhí)行耗時、內(nèi)存占用以及當(dāng)前頁面的網(wǎng)絡(luò)性能,資源占用。

還能查看最近的(10次)頁面性能的平均數(shù)。點(diǎn)擊“生成報表”按鈕會生成更詳細(xì)的數(shù)據(jù)報表概覽。

小結(jié)

Performance API 用來做前端性能監(jiān)控非常有用,它提供了很多方便測試我們程序性能的接口。比如mark和measure。很多優(yōu)秀的框架也用到了這個API進(jìn)行測試。

它里面就頻繁用到了mark和measure來測試程序性能。所以想要開發(fā)高性能的web程序,了解Performace API還是非常重要的。最后通過superProfiler工具可以更快更便捷的查找出性能問題,針對性的擊破問題,提高開發(fā)效率,提升用戶體驗(yàn)。當(dāng)然這只是前端性能優(yōu)化的第一步,道阻且長。希望大家提出問題和指出疑問,一起進(jìn)步。

轉(zhuǎn)載自騰訊新聞TNFE前端團(tuán)隊(duì)

總結(jié)

以上是生活随笔為你收集整理的前端白屏问题_深入理解前端性能监控的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。