Nodejs中分析web前端性能(window.performance)
阿新 • • 發佈:2019-04-07
代碼 web interact 返回值 efault 延遲 tab 前端性能 veh 在nodejs中,通過puppeteer來獲取web頁面中的window.performance對象,從而分析頁面的性能。下面直接上代碼。
const puppeteer = require(‘puppeteer‘); const path = require("path"); const logger=require("./log"); const log = logger.getPuppeteerRecordLogger() ; /* 啟動瀏覽器 */ async function launchBrowser(){ //啟動瀏覽器實例 [puppeteer.createBrowserFetcher([options])] let browser = await puppeteer.launch({ // 若是手動下載的chromium需要指定chromium地址, 默認引用地址為 /項目目錄/node_modules/puppeteer/.local-chromium/ //executablePath: ‘/Users/huqiyang/Documents/project/z/chromium/Chromium.app/Contents/MacOS/Chromium‘, //如果是訪問https頁面 此屬性會忽略https錯誤 ignoreHTTPSErrors: true, // 關閉headless模式, 不會打開瀏覽器 headless: true, //瀏覽器啟動參數 https://peter.sh/experiments/chromium-command-line-switches/ --timeout args:[‘--disk-cache-size=0‘,‘--disable-cache‘,‘--disable-infobars‘,‘--window-size=800,600‘,‘--ignore-certificate-errors‘,‘--enable-feaures‘], //是否為每個選項卡自動打開DevTools面板。 如果此選項為true,則headless選項將設置為false。 devtools: false, //Defaults to 30000 (30 seconds). Pass 0 to disable timeout. timeout: 0 //放慢puppeteer執行的動作,方便調試 //slowMo: 250 }); return browser ; } async function saveHarlog(url,dirPath,filename){ let homesite = url ; //保存的文件路徑 let harFilePath = path.join(dirPath,filename) ; //處理URL if(!(url.startsWith(‘http://‘) || url.startsWith(‘https://‘))){ url = "http://" + url ; } //打開瀏覽器 let browser = await launchBrowser() ; //創建一個新頁面 //let page = await browser.newPage(); const page = (await browser.pages())[0]; try{ await page.goto(url,{ timeout:0 }); /* 在page上下文中得到window.performance.timing */ const timing = await page.evaluate( _ => { const {navigationStart,unloadEventStart,unloadEventEnd, redirectStart,redirectEnd,fetchStart,domainLookupStart, domainLookupEnd,connectStart,connectEnd,secureConnectionStart, requestStart,responseStart,responseEnd,domLoading,domInteractive, domContentLoadedEventStart,domContentLoadedEventEnd,domComplete, loadEventStart,loadEventEnd} = window.performance.timing; return ({navigationStart:navigationStart, unloadEventStart:unloadEventStart, unloadEventEnd:unloadEventEnd, redirectStart:redirectStart, redirectEnd:redirectEnd, fetchStart:fetchStart, domainLookupStart:domainLookupStart, domainLookupEnd:domainLookupEnd, connectStart:connectStart, connectEnd:connectEnd, secureConnectionStart:secureConnectionStart, requestStart:requestStart, responseStart:responseStart, responseEnd:responseEnd, domLoading:domLoading, domInteractive:domInteractive, domContentLoadedEventStart:domContentLoadedEventStart, domContentLoadedEventEnd:domContentLoadedEventEnd, domComplete:domComplete, loadEventStart:loadEventStart, loadEventEnd:loadEventEnd}) }) log.info(‘--->‘ + JSON.stringify(timing)) ; if(timing){ //long 型的毫秒數。上一個文檔卸載(unload)結束時的UNIX時間戳。如果沒有上一個文檔,這個值會和fetchStart相同。 let navigationStart = timing.navigationStart ; //long 型的毫秒數.表征了unload事件拋出時的UNIX時間戳,如果沒有上一個文檔, 這個值會返回0 let unloadEventStart = timing.unloadEventStart ; //long 型的毫秒數,表征了unload事件處理完成時的UNIX時間戳。如果沒有上一個文檔, 這個值會返回0 let unloadEventEnd = timing.unloadEventEnd ; //long 型的毫秒數,表征了第一個HTTP重定向開始時的UNIX時間戳。如果沒有重定向,或者重定向中的一個不同源,這個值會返回0. let redirectStart = timing.redirectStart ; //long 型的毫秒數,表征了最後一個HTTP重定向完成時(也就是說是HTTP響應的最後一個比特直接被收到的時間)的UNIX時間戳。如果沒有重定向,或者重定向中的一個不同源,這個值會返回0. let redirectEnd = timing.redirectEnd ; //long 型的毫秒數,表征了瀏覽器準備好使用HTTP請求來獲取(fetch)文檔的UNIX時間戳。這個時間點會在檢查任何應用緩存之前。 let fetchStart = timing.fetchStart ; //long 型的毫秒數,表征了域名查詢開始的UNIX時間戳。如果使用了持續連接(persistent connection),或者這個信息存儲到了緩存或者本地資源上,這個值將和fetchStart一致。 let domainLookupStart = timing.domainLookupStart ; //long 型的毫秒數,表征了域名查詢結束的UNIX時間戳。如果使用了持續連接(persistent connection),或者這個信息存儲到了緩存或者本地資源上,這個值將和 fetchStart一致。 let domainLookupEnd = timing.domainLookupEnd ; //long 型的毫秒數,返回HTTP請求開始向服務器發送時的Unix毫秒時間戳。如果使用持久連接(persistent connection),則返回值等同於fetchStart屬性的值。 let connectStart = timing.connectStart ; //long 型的毫秒數,返回瀏覽器與服務器之間的連接建立時的Unix毫秒時間戳。如果建立的是持久連接,則返回值等同於fetchStart屬性的值。連接建立指的是所有握手和認證過程全部結束。 let connectEnd = timing.connectEnd ; //long 型的毫秒數,返回瀏覽器與服務器開始安全鏈接的握手時的Unix毫秒時間戳。如果當前網頁不要求安全連接,則返回0 let secureConnectionStart = timing.secureConnectionStart ; //long 型的毫秒數,返回瀏覽器向服務器發出HTTP請求時(或開始讀取本地緩存時)的Unix毫秒時間戳 let requestStart = timing.requestStart ; //long 型的毫秒數,返回瀏覽器從服務器收到(或從本地緩存讀取)第一個字節時的Unix毫秒時間戳。如果傳輸層在開始請求之後失敗並且連接被重開,該屬性將會被數制成新的請求的相對應的發起時間。 let responseStart = timing.responseStart ; //long 型的毫秒數,返回瀏覽器從服務器收到(或從本地緩存讀取,或從本地資源讀取)最後一個字節時(如果在此之前HTTP連接已經關閉,則返回關閉時)的Unix毫秒時間戳。 let responseEnd = timing.responseEnd ; //long 型的毫秒數,返回當前網頁DOM結構開始解析時(即Document.readyState屬性變為“loading”、相應的 readystatechange事件觸發時)的Unix毫秒時間戳。 let domLoading = timing.domLoading ; //long 型的毫秒數,返回當前網頁DOM結構結束解析、開始加載內嵌資源時(即Document.readyState屬性變為“interactive”、相應的readystatechange事件觸發時)的Unix毫秒時間戳 let domInteractive = timing.domInteractive ; //ong 型的毫秒數,返回當解析器發送DOMContentLoaded 事件,即所有需要被執行的腳本已經被解析時的Unix毫秒時間戳 let domContentLoadedEventStart = timing.domContentLoadedEventStart ; //long 型的毫秒數,返回當所有需要立即執行的腳本已經被執行(不論執行順序)時的Unix毫秒時間戳 let domContentLoadedEventEnd = timing.domContentLoadedEventEnd ; //long 型的毫秒數,返回當前文檔解析完成,即Document.readyState 變為 ‘complete‘且相對應的readystatechange 被觸發時的Unix毫秒時間戳 let domComplete = timing.domComplete ; //long 型的毫秒數,返回該文檔下,load事件被發送時的Unix毫秒時間戳。如果這個事件還未被發送,它的值將會是0 let loadEventStart = timing.loadEventStart ; //long 型的毫秒數,返回當load事件結束,即加載事件完成時的Unix毫秒時間戳。如果這個事件還未被發送,或者尚未完成,它的值將會是0 let loadEventEnd = timing.loadEventEnd ; //呈現了如何導航到當前文檔的信息 //let navigation = performance.navigation ; } }catch(error){ log.info(‘resovle error :‘ + url + "; error message:" + error) ; }finally{ if(browser){ await browser.close(); } } } exports.launchBrowser = launchBrowser; exports.saveHarlog = saveHarlog;
指標說明
//@param t -> timing async function getPerformanceTiming (t) { if (!t) { log.info(‘not allow null‘); return; } var times = {}; //【重要】頁面加載完成的時間 //【原因】這幾乎代表了用戶等待頁面可用的時間 times.loadPage = t.loadEventEnd - t.navigationStart; //【重要】解析 DOM 樹結構的時間 //【原因】反省下你的 DOM 樹嵌套是不是太多了! times.domReady = t.domComplete - t.responseEnd; //【重要】重定向的時間 //【原因】拒絕重定向!比如,http://example.com/ 就不該寫成 http://example.com times.redirect = t.redirectEnd - t.redirectStart; //【重要】DNS 查詢時間 //【原因】DNS 預加載做了麽?頁面內是不是使用了太多不同的域名導致域名查詢的時間太長? // 可使用 HTML5 Prefetch 預查詢 DNS ,見:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364) times.lookupDomain = t.domainLookupEnd - t.domainLookupStart; //【重要】讀取頁面第一個字節的時間 //【原因】這可以理解為用戶拿到你的資源占用的時間,加異地機房了麽,加CDN 處理了麽?加帶寬了麽?加 CPU 運算速度了麽? // TTFB 即 Time To First Byte 的意思 // 維基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte times.ttfb = t.responseStart - t.navigationStart; //【重要】內容加載完成的時間 //【原因】頁面內容經過 gzip 壓縮了麽,靜態資源 css/js 等壓縮了麽? times.request = t.responseEnd - t.requestStart; //【重要】執行 onload 回調函數的時間 //【原因】是否太多不必要的操作都放到 onload 回調函數裏執行了,考慮過延遲加載、按需加載的策略麽? times.loadEvent = t.loadEventEnd - t.loadEventStart; // DNS 緩存時間 times.appcache = t.domainLookupStart - t.fetchStart; // 卸載頁面的時間 times.unloadEvent = t.unloadEventEnd - t.unloadEventStart; // TCP 建立連接完成握手的時間 times.connect = t.connectEnd - t.connectStart; return times; }
Nodejs中分析web前端性能(window.performance)