<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何使用 Performance API 讓您的網(wǎng)站更快

          共 8546字,需瀏覽 18分鐘

           ·

          2021-06-24 17:33

          本教程介紹了如何使用 Performance API 記錄來(lái)自訪問(wèn)您的應(yīng)用程序的真實(shí)用戶的類似 DevTool 的統(tǒng)計(jì)信息。

          使用瀏覽器 DevTools 評(píng)估 Web 應(yīng)用程序性能很有用,但復(fù)制實(shí)際使用情況并不容易。使用不同設(shè)備、瀏覽器和網(wǎng)絡(luò)的不同地點(diǎn)的人都會(huì)有不同的體驗(yàn)。

          性能 API 簡(jiǎn)介

          性能API使用緩沖記錄DevTool般在你的網(wǎng)頁(yè)的生命周期的特定點(diǎn)對(duì)象屬性指標(biāo)。這些要點(diǎn)包括:

          1. 頁(yè)面導(dǎo)航:記錄頁(yè)面加載重定向、連接、握手、DOM 事件等。

          2. 資源加載:記錄圖片、CSS、腳本、Ajax 調(diào)用等資源加載。

          3. Paint metrics:記錄瀏覽器渲染信息。

          4. 自定義性能:記錄任意應(yīng)用程序處理時(shí)間以查找慢功能。

          所有 API 都在客戶端 JavaScript 中可用,包括Web Workers。您可以使用以下方法檢測(cè) API 支持:

          if ('performance' in window) {

          // call Performance APIs

          }

          注意:請(qǐng)注意,盡管實(shí)現(xiàn)了大部分 API,但 Safari 并不支持所有方法。

          自定義(用戶)性能 API 也復(fù)制到:

          • Node.js 內(nèi)置performance_hook模塊,以及

          • Deno性能 API(使用它的腳本必須在--allow-hrtime許可下運(yùn)行)。

          Date()不夠好?

          您可能已經(jīng)看過(guò)使用該Date()函數(shù)記錄經(jīng)過(guò)時(shí)間的示例。例如:

          const start = new Date();

          // ... run code ...

          const elapsed = new Date() - start;

          但是,Date()計(jì)算僅限于最接近的毫秒并基于系統(tǒng)時(shí)間,操作系統(tǒng)可以隨時(shí)更新系統(tǒng)時(shí)間。

          Performance API 使用一個(gè)單獨(dú)的、更高分辨率的計(jì)時(shí)器,可以在幾分之一毫秒內(nèi)進(jìn)行記錄。它還提供了以其他方式無(wú)法記錄的指標(biāo),例如重定向和 DNS 查找時(shí)間。

          記錄性能指標(biāo)

          如果您可以將其記錄在某處,則在客戶端代碼中計(jì)算性能指標(biāo)非常有用。您可以使用 Ajax Fetch / XMLHttpRequest請(qǐng)求或Beacon API將統(tǒng)計(jì)信息發(fā)送到您的服務(wù)器進(jìn)行分析。

          或者,大多數(shù)分析系統(tǒng)提供自定義事件類 API 來(lái)記錄時(shí)間。例如,Google Analytics User Timings API可以DOMContentLoaded通過(guò)傳遞類別 ( 'pageload')、變量名稱 ( "DOMready") 和值來(lái)記錄時(shí)間:

          const pageload = performance.getEntriesByType( 'navigation' )[0];

          ga('send', 'timing', 'pageload', 'DOMready', pageload.domContentLoadedEventStart);

          此示例使用頁(yè)面導(dǎo)航計(jì)時(shí) API。所以讓我們從那里開始……

          頁(yè)面導(dǎo)航時(shí)序

          在快速連接上測(cè)試您的網(wǎng)站不太可能代表用戶體驗(yàn)。瀏覽器 DevTools網(wǎng)絡(luò)選項(xiàng)卡允許您調(diào)節(jié)速度,但它無(wú)法模擬較差或斷斷續(xù)續(xù)的 3G 信號(hào)。

          Navigation Timing API 將單個(gè)PerformanceNavigationTiming對(duì)象推送到性能緩沖區(qū)。它包含真實(shí)用戶觀察到的有關(guān)重定向、加載時(shí)間、文件大小、DOM 事件等的信息。

          通過(guò)運(yùn)行訪問(wèn)對(duì)象:

          const pagePerf = performance.getEntriesByType( 'navigation' );

          或者通過(guò)將頁(yè)面 URL ( window.location)傳遞給 來(lái)訪問(wèn)它getEntriesByName() method

          const pagePerf = performance.getEntriesByName( window.location );

          兩者都返回一個(gè)包含具有只讀屬性的對(duì)象的單個(gè)元素的數(shù)組。例如:

          [
          {
          name: "https://site.com/",
          initiatorType: "navigation",
          entryType: "navigation",
          initiatorType: "navigation",
          type: "navigate",
          nextHopProtocol: "h2",
          startTime: 0
          ...
          }
          ]

          該對(duì)象包括資源標(biāo)識(shí)屬性

          財(cái)產(chǎn)描述
          名稱資源網(wǎng)址
          條目類型性能類型——"navigation"對(duì)于頁(yè)面,"resource"對(duì)于資產(chǎn)
          發(fā)起者類型啟動(dòng)下載的資源 -"navigation"用于頁(yè)面
          下一跳協(xié)議網(wǎng)絡(luò)協(xié)議
          服務(wù)器定時(shí)PerformanceServerTiming對(duì)象數(shù)組

          注意:performanceServerTiming namedescriptiondurationmetrics由服務(wù)器響應(yīng)寫入 HTTPServer-Timing標(biāo)頭。

          該對(duì)象包括相對(duì)于頁(yè)面加載開始的以毫秒為單位的資源計(jì)時(shí)屬性。通常按以下順序預(yù)計(jì)時(shí)間:

          財(cái)產(chǎn)描述
          開始時(shí)間獲取開始時(shí)的時(shí)間戳 -0用于頁(yè)面
          工人開始啟動(dòng) Service Worker 之前的時(shí)間戳
          重定向開始第一次重定向的時(shí)間戳
          重定向結(jié)束收到上次重定向的最后一個(gè)字節(jié)后的時(shí)間戳
          獲取開始獲取資源之前的時(shí)間戳
          域查找開始DNS 查找前的時(shí)間戳
          域查找結(jié)束DNS 查找后的時(shí)間戳
          連接開始建立服務(wù)器連接前的時(shí)間戳
          連接結(jié)束建立服務(wù)器連接后的時(shí)間戳
          安全連接啟動(dòng)SSL 握手前的時(shí)間戳
          請(qǐng)求開始瀏覽器請(qǐng)求前的時(shí)間戳
          響應(yīng)開始瀏覽器收到第一個(gè)字節(jié)數(shù)據(jù)時(shí)的時(shí)間戳
          響應(yīng)結(jié)束收到最后一個(gè)字節(jié)數(shù)據(jù)后的時(shí)間戳
          期間startTimeresponseEnd之間經(jīng)過(guò)的時(shí)間

          該對(duì)象包括以字節(jié)為單位下載大小屬性

          財(cái)產(chǎn)描述
          傳輸大小資源大小,包括標(biāo)題和正文
          編碼體尺寸解壓前的資源體大小
          解碼體尺寸解壓后的資源體大小

          最后,該對(duì)象包括進(jìn)一步的導(dǎo)航和 DOM 事件屬性(在 Safari 中不可用):

          財(cái)產(chǎn)描述
          類型要么"navigate","reload","back_forward"或者"prerender"
          重定向計(jì)數(shù)重定向次數(shù)
          卸載事件開始unload上一個(gè)文檔事件之前的時(shí)間戳
          卸載事件結(jié)束unload上一個(gè)文檔事件之后的時(shí)間戳
          domInteractiveHTML 解析和 DOM 構(gòu)建完成時(shí)的時(shí)間戳
          domContentLoadedEventStart

          運(yùn)行DOMContentLoaded事件處理程序之前的時(shí)間戳

          domContentLoadedEventEnd

          運(yùn)行DOMContentLoaded事件處理程序后的時(shí)間戳

          domCompleteDOM 構(gòu)建和DOMContentLoaded事件完成時(shí)的時(shí)間戳
          加載事件開始頁(yè)面load事件觸發(fā)前的時(shí)間戳
          加載事件結(jié)束頁(yè)面load事件后的時(shí)間戳。下載所有資產(chǎn)

          在頁(yè)面完全加載后記錄頁(yè)面加載指標(biāo)的示例:

          'performance' in window && window.addEventListener('load', () => {

          const
          pagePerf = performance.getEntriesByName( window.location )[0],
          pageDownload = pagePerf.duration,
          pageDomComplete = pagePerf.domComplete;

          });

          頁(yè)面資源時(shí)序

          PerformanceResourceTiming每當(dāng)頁(yè)面加載圖像、字體、CSS 文件、JavaScript 文件或任何其他項(xiàng)目等資產(chǎn)時(shí),Resource Timing API 都會(huì)將對(duì)象推送到性能緩沖區(qū)。跑步:

          const resPerf = performance.getEntriesByType( 'resource' );

          這將返回一組資源計(jì)時(shí)對(duì)象。這些具有與上面顯示頁(yè)面計(jì)時(shí)相同的屬性,但沒(méi)有導(dǎo)航和 DOM 事件信息。

          這是一個(gè)示例結(jié)果:

          [
          {
          name: "https://site.com/style.css",
          entryType: "resource",
          initiatorType: "link",
          fetchStart: 150,
          duration: 300
          ...
          },
          {
          name: "https://site.com/script.js",
          entryType: "resource",
          initiatorType: "script",
          fetchStart: 302,
          duration: 112
          ...
          },
          ...
          ]

          可以通過(guò)將其 URL 傳遞給.getEntriesByName()方法來(lái)檢查單個(gè)資源:

          const resourceTime = performance.getEntriesByName('https://site.com/style.css');

          這將返回一個(gè)包含單個(gè)元素的數(shù)組:

          [
          {
          name: "https://site.com/style.css",
          entryType: "resource",
          initiatorType: "link",
          fetchStart: 150,
          duration: 300
          ...
          }
          ]

          您可以使用 API 報(bào)告每個(gè) CSS 文件的加載時(shí)間和解壓縮大小:

          // array of CSS files, load times, and file sizes
          const css = performance.getEntriesByType('resource')
          .filter( r => r.initiatorType === 'link' && r.name.includes('.css'))
          .map( r => ({

          name: r.name,
          load: r.duration + 'ms',
          size: r.decodedBodySize + ' bytes'

          }) );

          css數(shù)組現(xiàn)在包含每個(gè) CSS 文件的對(duì)象。例如:

          [
          {
          name: "https://site.com/main.css",
          load: "155ms",
          size: "14304 bytes"
          },
          {
          name: "https://site.com/grid.css",
          load: "203ms",
          size: "5696 bytes"
          }
          ]

          注意:負(fù)載和大小為零表示資產(chǎn)已被緩存。

          至少 150 個(gè)資源指標(biāo)對(duì)象將被記錄到性能緩沖區(qū)。您可以使用.setResourceTimingBufferSize(N)方法定義一個(gè)特定的數(shù)字。例如:

          // record 500 resources
          performance.setResourceTimingBufferSize(500);

          可以使用 清除現(xiàn)有指標(biāo).clearResourceTimings() method。

          瀏覽器繪制時(shí)間

          First Contentful Paint (FCP)衡量用戶導(dǎo)航到您的頁(yè)面后呈現(xiàn)內(nèi)容所需的時(shí)間。Chrome 的 DevTool Lighthouse 面板的Performance部分顯示了該指標(biāo)。Google 認(rèn)為 FCP 時(shí)間少于 2 秒是好的,并且您的頁(yè)面將比 Web 的 75% 顯示得更快。

          在以下情況下,Paint Timing API 將兩個(gè)記錄兩個(gè)PerformancePaintTiming對(duì)象推送到性能緩沖區(qū):

          • first-paint發(fā)生:瀏覽器繪制第一個(gè)像素,并且

          • first-contentful-paint發(fā)生:瀏覽器繪制 DOM 內(nèi)容的第一項(xiàng)

          運(yùn)行時(shí),兩個(gè)對(duì)象都以數(shù)組形式返回:

          const paintPerf = performance.getEntriesByType( 'paint' );

          結(jié)果示例:

          [
          {
          "name": "first-paint",
          "entryType": "paint",
          "startTime": 125
          },
          {
          "name": "first-contentful-paint",
          "entryType": "paint",
          "startTime": 127
          }
          ]

          開始時(shí)間是相對(duì)于初始頁(yè)面加載。

          用戶計(jì)時(shí)

          Performance API 可用于為您自己的應(yīng)用程序功能計(jì)時(shí)。所有用戶計(jì)時(shí)方法都可以在客戶端 JavaScript、Web Workers、Deno 和 Node.js 中使用。

          請(qǐng)注意,Node.js 腳本必須加載Performance hooks( perf_hooks) 模塊。

          CommonJSrequire語(yǔ)法:

          const { performance } = require('perf_hooks');

          或者 ES 模塊import語(yǔ)法:

          import { performance } from 'perf_hooks';

          最簡(jiǎn)單的選項(xiàng)是performance.now(),它返回進(jìn)程生命周期開始時(shí)的高分辨率時(shí)間戳。

          您可以performance.now()用于簡(jiǎn)單的計(jì)時(shí)器。例如:

          const start = performance.now();

          // ... run code ...

          const elapsed = performance.now() - start;

          注意:非標(biāo)準(zhǔn)timeOrigin屬性返回 Unix 時(shí)間的時(shí)間戳。它可以在 Node.js 和瀏覽器 JavaScript 中使用,但不能在 IE 和 Safari 中使用。

          performance.now()在管理多個(gè)計(jì)時(shí)器時(shí)很快變得不切實(shí)際。該.mark()方法將一個(gè)命名的PerformanceMark 對(duì)象對(duì)象添加到性能緩沖區(qū)。例如:

          performance.mark('script:start');

          performance.mark('p1:start');
          // ... run process 1 ...
          performance.mark('p1:end');

          performance.mark('p2:start');
          // ... run process 2 ...
          performance.mark('p2:end');

          performance.mark('script:end');

          以下代碼返回一個(gè)標(biāo)記對(duì)象數(shù)組:

          const marks = performance.getEntriesByType( 'mark' );

          entryType,namestartTime屬性:

          [
          {
          entryType: "mark",
          name: "script:start",
          startTime: 100
          },
          {
          entryType: "mark",
          name: "p1:start",
          startTime: 200
          },
          {
          entryType: "mark",
          name: "p1:end",
          startTime: 300
          },
          ...
          ]

          可以使用該.measure()方法計(jì)算兩個(gè)標(biāo)記之間經(jīng)過(guò)的時(shí)間。它傳遞了一個(gè)度量名稱、開始標(biāo)記名稱(或null使用零)和結(jié)束標(biāo)記名稱(或null使用當(dāng)前時(shí)間):

          performance.measure('p1', 'p1:start', 'p1:end');
          performance.measure('script', null, 'script:end');

          每次調(diào)用都會(huì)將具有計(jì)算持續(xù)時(shí)間的PerformanceMeasure對(duì)象推送到性能緩沖區(qū)??梢酝ㄟ^(guò)運(yùn)行來(lái)訪問(wèn)一系列度量:

          const measures = performance.getEntriesByType( 'measure' );

          例子:

          [
          {
          entryType: "measure",
          name: "p1",
          startTime: 200,
          duration: 100
          },
          {

          entryType: "measure",
          name: "script",
          startTime: 0,
          duration: 500
          }
          ]

          可以使用以下.getEntriesByName()方法按名稱檢索標(biāo)記或測(cè)量對(duì)象:

          performance.getEntriesByName( 'p1' );

          其他方法:

          • .getEntries(): 返回所有性能條目的數(shù)組。

          • .clearMarks( [name] ): 清除命名標(biāo)記(不帶名稱運(yùn)行以清除所有標(biāo)記)

          • .clearMeasures( [name] ): 清除已命名的度量(不帶名稱運(yùn)行以清除所有度量)

          一個(gè)PerformanceObserver可以觀看更改到緩沖區(qū),并運(yùn)行一個(gè)函數(shù),當(dāng)特定對(duì)象出現(xiàn)。觀察者函數(shù)定義有兩個(gè)參數(shù):

          1. list: 觀察者條目

          2. observer(可選觀察者對(duì)象


          function performanceHandler(list, observer) {

          list.getEntries().forEach(entry => {

          console.log(`name : ${ entry.name }`);
          console.log(`type : ${ entry.type }`);
          console.log(`duration: ${ entry.duration }`);

          // other code, e.g.
          // send data via an Ajax request

          });

          }

          這個(gè)函數(shù)被傳遞給一個(gè)新PerformanceObserver對(duì)象。該.observe()方法然后將觀察到的entryTypes(通常"mark""measure"和/或"resource"):

          let observer = new PerformanceObserver( performanceHandler );
          observer.observe( { entryTypes: [ 'mark', 'measure' ] } );

          performanceHandler()每當(dāng)將新標(biāo)記或度量對(duì)象推送到性能緩沖區(qū)時(shí),該函數(shù)就會(huì)運(yùn)行。

          自我分析 API

          自我剖析API是關(guān)系到性能API和可以幫助找到低效或不必要的后臺(tái)功能,而無(wú)需手動(dòng)設(shè)置標(biāo)志和措施。

          示例代碼:

          // new profiler, 10ms sample rate
          const profile = await performance.profile({ sampleInterval: 10 });

          // ... run code ...

          // stop profiler, get trace
          const trace = await profile.stop();

          跟蹤返回有關(guān)在每個(gè)采樣間隔執(zhí)行的腳本、函數(shù)和行號(hào)的數(shù)據(jù)。重復(fù)引用相同的代碼可能表明進(jìn)一步優(yōu)化是可能的。

          API 目前正在開發(fā)中(請(qǐng)參閱Chrome 狀態(tài))并且可能會(huì)發(fā)生變化。

          調(diào)整應(yīng)用程序性能

          性能 API 提供了一種方法來(lái)衡量網(wǎng)站和應(yīng)用程序在真實(shí)設(shè)備上的網(wǎng)站和應(yīng)用程序速度,這些設(shè)備由真實(shí)的人在不同位置使用一系列連接。它可以輕松地為每個(gè)人整理類似 DevTool 的指標(biāo)并識(shí)別潛在的瓶頸。

          解決這些性能問(wèn)題是另一回事,但SitePoint Jump Start Web Performance 一書會(huì)有所幫助。它提供了一系列快餐、簡(jiǎn)單的食譜和改變生活的飲食,讓您的網(wǎng)站更快、響應(yīng)更快。

          往期推薦

          Vite 太快了,煩死了,是時(shí)候該小睡一會(huì)了。


          如何實(shí)現(xiàn)比 setTimeout 快 80 倍的定時(shí)器?


          萬(wàn)字長(zhǎng)文!總結(jié)Vue 性能優(yōu)化方式及原理


          90 行代碼的 webpack,你確定不學(xué)嗎?


          最后





          如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:

          1. 點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)

          2. 歡迎加我微信「huab119」拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...

            關(guān)注公眾號(hào)「前端勸退師」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。



          點(diǎn)個(gè)在看支持我吧,轉(zhuǎn)發(fā)就更好了



          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  香蕉网站看片 | 伊人在线成人 | 大香蕉精品网 | 免费一级特黄大学生毛片 | 69自拍视频 |