快速定位網(wǎng)站性能問題,提前下班!

大家好,我是小雨小雨,致力于分享有趣的、實(shí)用的技術(shù)文章。
內(nèi)容分為翻譯和原創(chuàng),如果有問題,歡迎隨時(shí)評(píng)論或私信,希望和大家一起進(jìn)步。
分享不易,希望能夠得到大家的支持和關(guān)注。

查看network時(shí)間

直接來一張大圖你怕不怕?哈哈
咱們先看看谷歌瀏覽器network中waterfall各字段的含義哈。簡(jiǎn)單看下就成,用到了再查不耽誤的。

image
  • Queueing: 排隊(duì)時(shí)間,比如出現(xiàn)以下幾種情況的時(shí)候,將進(jìn)入排隊(duì)

    1. 當(dāng)前請(qǐng)求前有優(yōu)先級(jí)更高的其他請(qǐng)求
    2. HTTP的1.0和1.1版本中,如果對(duì)一個(gè)域發(fā)送超過六個(gè)請(qǐng)求,那么之后的請(qǐng)求需要等待之前請(qǐng)求處理完畢,這是瀏覽器對(duì)tcp連接數(shù)的限制。我們可以將資源托管到不同域下來緩解
    3. 瀏覽器在進(jìn)行其他操作,比如分配硬盤內(nèi)存
  • Stalled: 發(fā)送請(qǐng)求之前等待的時(shí)間。它可能因?yàn)檫M(jìn)入隊(duì)列的任意原因而被阻塞。這個(gè)時(shí)間包括代理協(xié)商的時(shí)間

  • DNS Lookup: dns解析時(shí)間。線路為: 瀏覽器緩存 => 操作系統(tǒng)緩存 => 路由器緩存 => 本地hosts文件 => dns服務(wù)器

  • Waiting (TTFB): 瀏覽器從發(fā)送請(qǐng)求到接收到服務(wù)器第一個(gè)字節(jié)的時(shí)間,全拼: Time To First Byte,包含這幾個(gè)操作: DNS解析 + TCP三次握手 + HTTP請(qǐng)求 + 第一字節(jié)返回

  • Content Download: 內(nèi)容下載時(shí)間

非 常用
  • ssl: ssl握手時(shí)間
  • Proxy negotiation: 代理協(xié)商時(shí)間
  • Request sent: 發(fā)送請(qǐng)求這一操作所花費(fèi)的時(shí)間,一般情況下很短
  • ServiceWorker Preparation: service worker啟動(dòng)時(shí)間
  • Request to ServiceWorker: 請(qǐng)求發(fā)送到service worker的時(shí)間
  • Receiving Push: 收到服務(wù)端發(fā)送的數(shù)據(jù)的時(shí)間(http2.0支持)
  • Reading Push: 讀取之前緩存的服務(wù)器推送的數(shù)據(jù)的時(shí)間(http2.0支持)

Queueing&TTFB

讓瀏覽器說話

常見的一個(gè)問題是:說說從輸入url到瀏覽器頁面展示這個(gè)流程,這次,只說瀏覽器接收到html后,瀏覽器做了什么,并且是讓瀏覽器自己說,我們就看著。

下面實(shí)例代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./normal.js"></script>
    <script defer src="./defer.js"></script>
    <script async src="./async.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function fengshiyu () {
            const box = document.querySelector('.box');
            const arr = new Array(1000).fill(1);
            let vDom = '';
            
            arr.forEach((a, i) => {
                vDom += `<p>${i}</p>`;
            });

            box.innerHTML = vDom;
        });
    </script>
</head>
<body>
    <img src="./aCxZpaq.png" alt="">
    <div class="box"></div>
    <h1>你哈哈哦</h1>
</body>
</html>

其中三個(gè)js文件都是近乎一樣的內(nèi)容

const deferArr = new Array(1000).fill(2);

deferArr.forEach((element, i) => {
    console.log(i, element);
});

node啟動(dòng)服務(wù)去服務(wù)這幾個(gè)文件,然后我們聽瀏覽器說吧~

從這開始,我就不是小雨了,我是瀏覽器,記住,我是瀏覽器!

大家好,我是瀏覽器,剛才小雨用我訪問了一個(gè)頁面,服務(wù)器大哥已經(jīng)把內(nèi)容返回給我了,我現(xiàn)在要給小雨展示出來。

上performance(谷歌瀏覽器開發(fā)者工具performance面板)~

首先,我得看看html里都有啥(逐行消化解析)。

我看到了有html,有head,誒還有幾個(gè)script,那我得根據(jù)情況暫停一下了,不能憨憨一樣一直往下看,不然這幾個(gè)js要是操作dom了,那我不白渲染了嗎?

那我就先加載這幾個(gè)script吧,等等,小雨這個(gè)貨居然還加deferasync,那就按我的規(guī)則來吧,我先把這三個(gè)script下載一下,對(duì)于deferasync可以與html解析并行執(zhí)行,下載完之后,除了defer外,我都得立刻執(zhí)行,不敢有絲毫猶豫。defer呢,我得在document解析完,并在DOMContentLoad之前使用它,誒,就是這么麻煩~

image

上途中上方是network時(shí)間線,下面是主線程時(shí)間線

怎么?你說影響defer和async影響到html解析了?沒有啊,他們那是占了normal的光~

下載完之后,就各自為營(yíng),按部就班的執(zhí)行啦。

image

看到?jīng)],就算defer寫到async的上面,也不一定就在async前面執(zhí)行,defer肯定得在DOMContentLoad之前執(zhí)行,而async的話,啥時(shí)候完事啥時(shí)候執(zhí)行。也就是說,只有defer不會(huì)影響html解析,所以啊,如果你們要想加快頁面顯示的話,就視情況多用defer吧。還有,這倆屬性只有script在head中才會(huì)生效嗷。

  • 放到head標(biāo)簽內(nèi),啥都不加的script
image
  • 放到body標(biāo)簽內(nèi),啥都不加的script
image
  • 放到head標(biāo)簽內(nèi),加defer的script
image
  • 放到head標(biāo)簽內(nèi),加async的script
image

再往后就會(huì)執(zhí)行頁面的布局和渲染啦~

對(duì)了,再囑咐你們一點(diǎn),匿名函數(shù)我只能用統(tǒng)一的命名顯示出來,所以你們調(diào)試的時(shí)候,估計(jì)不會(huì)很愉快。要根據(jù)情況決定是否真的有必要使用匿名函數(shù)啊~

image

我回來了~

所以說,我們首先可以合理加載執(zhí)行script來減少html解析的阻塞,其實(shí)還有css的元素,因?yàn)閏ss會(huì)阻塞css的執(zhí)行,畢竟js有可能要操作css嘛。

還有什么回流、重繪什么的,這里就不再重復(fù)了。

有興趣的朋友可以用某些網(wǎng)站查看一些performance,看看自己的掌握程度,有問題歡迎討論。

猜測(cè),類似詞法解析和語法解析,詞法解析先獲取到要下載的內(nèi)容,或者綁定在document上的事件,所以之后出發(fā)DOMContentLoad的時(shí)候會(huì)觸發(fā)之前綁定的事件,而且沒有在主線程中顯示

總結(jié)

本文簡(jiǎn)單的說了兩個(gè)點(diǎn),一是network的timing欄,二是performance panel,只要掌握了這兩個(gè)功能的使用方法,就可以快速定位網(wǎng)站性能問題,進(jìn)而進(jìn)行優(yōu)化,早點(diǎn)下班美滋滋~

常見優(yōu)化方案

  • 開啟壓縮
  • 圖片使用webp
  • cdn
  • 提取關(guān)鍵幀資源,優(yōu)先加載
  • 代碼分片,延遲加載
  • 預(yù)加載,preload prefetch等
  • script defer async
  • 域名分片,減少請(qǐng)求數(shù)
  • 服務(wù)端渲染
  • 如果已經(jīng)升級(jí)為https,可以考慮使用http2.0。兩個(gè)點(diǎn):一個(gè)頭信息壓縮,二是解決了隊(duì)頭阻塞問題,三是增加了服務(wù)端push。
  • 資源預(yù)取,混合應(yīng)用可以加離線寶
  • 在mvvm類框架進(jìn)行前端渲染,我們可以使用defer加在我們的內(nèi)容,在配上骨架圖,保證用戶看到的不是空白的頁面。
  • 當(dāng)然少不了我們的業(yè)務(wù)代碼,好的代碼會(huì)讓網(wǎng)站更穩(wěn)定的運(yùn)行下去
  • 分析network的timing,然后通過本文最開始提及的各字段分析問題

如果你看過一些語言和框架,你會(huì)發(fā)現(xiàn)大同小異


不過,這些個(gè)優(yōu)化只是在我們看來,還是不夠完善的,我們需要知道真實(shí)的用戶環(huán)境下是怎么樣的,需要RUM(Real User Monitoring: 真實(shí)用戶數(shù)據(jù)監(jiān)測(cè)),寫個(gè)腳本來收集用戶的訪問情況,并可視化,作為我們的性能指標(biāo)再好不過了。

這里推薦采用三組數(shù)據(jù):

  • 平均值: 平均速度
  • 中位值: 中間速度
  • 第95百分位值: 弱勢(shì)網(wǎng)絡(luò)、瀏覽器等數(shù)據(jù),更全面

可以使用performanceResource Timing API來進(jìn)行數(shù)據(jù)收集

想做更多的優(yōu)化,還是應(yīng)該了解一下chromium源碼,錦上添花。

如果不想看源碼,那就讓瀏覽器來告訴我們,它做了什么吧~

最后,在網(wǎng)站優(yōu)化方面,前端能做的不是很多,真正的大頭是在op和服務(wù)端,所以說,轉(zhuǎn)行吧~ ??

timing-explanation

timing

script 的 defer 和 async 官方解釋

頁面生命周期

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容