Nodejsでwebフロントエンドの性能を分析する(window.performance)


nodejsでは、pppeteerを通じてウェブページの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;
}