From c9ea68bf1e2092baabbd85cfea153d7c175e162f Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 28 Jan 2025 21:42:29 -0800 Subject: [PATCH] Wrap individual puppeteer navigations in try/catch block --- cli/commands/benchmark-web-vitals.mjs | 210 +++++++++++++------------- 1 file changed, 107 insertions(+), 103 deletions(-) diff --git a/cli/commands/benchmark-web-vitals.mjs b/cli/commands/benchmark-web-vitals.mjs index 8a5a1a9..e3041f8 100644 --- a/cli/commands/benchmark-web-vitals.mjs +++ b/cli/commands/benchmark-web-vitals.mjs @@ -460,121 +460,125 @@ async function benchmarkURL( } for ( let requestNum = 0; requestNum < params.amount; requestNum++ ) { - if ( logProgress ) { - logPartial( - `Benchmarking ${ requestNum + 1 } / ${ params.amount }...` - ); - } - const page = await browser.newPage(); - await page.setBypassCSP( true ); // Bypass CSP so the web vitals script tag can be injected below. - if ( params.cpuThrottleFactor ) { - await page.emulateCPUThrottling( params.cpuThrottleFactor ); - } - - if ( params.networkConditions ) { - await page.emulateNetworkConditions( params.networkConditions ); - } + try { + if ( logProgress ) { + logPartial( + `Benchmarking ${ requestNum + 1 } / ${ params.amount }...` + ); + } + const page = await browser.newPage(); + await page.setBypassCSP( true ); // Bypass CSP so the web vitals script tag can be injected below. + if ( params.cpuThrottleFactor ) { + await page.emulateCPUThrottling( params.cpuThrottleFactor ); + } - if ( params.emulateDevice ) { - await page.emulate( params.emulateDevice ); - } - if ( params.windowViewport ) { - await page.setViewport( { - ...( params.emulateDevice - ? params.emulateDevice.viewport - : {} ), - ...params.windowViewport, - } ); - } + if ( params.networkConditions ) { + await page.emulateNetworkConditions( params.networkConditions ); + } - // Load the page. - const urlObj = new URL( url ); - urlObj.searchParams.append( 'rnd', String( Math.random() ) ); + if ( params.emulateDevice ) { + await page.emulate( params.emulateDevice ); + } + if ( params.windowViewport ) { + await page.setViewport( { + ...( params.emulateDevice + ? params.emulateDevice.viewport + : {} ), + ...params.windowViewport, + } ); + } - // Make sure any username and password in the URL is passed along for authentication. - if ( urlObj.username && urlObj.password ) { - await page.authenticate( { - username: urlObj.username, - password: urlObj.password, - } ); - } + // Load the page. + const urlObj = new URL( url ); + urlObj.searchParams.append( 'rnd', String( Math.random() ) ); - const response = await page.goto( urlObj.toString(), { - waitUntil: 'networkidle0', - } ); - if ( scriptTag ) { - await page.addScriptTag( { content: scriptTag, type: 'module' } ); - } + // Make sure any username and password in the URL is passed along for authentication. + if ( urlObj.username && urlObj.password ) { + await page.authenticate( { + username: urlObj.username, + password: urlObj.password, + } ); + } - if ( response.status() !== 200 ) { - if ( logProgress ) { - log( - formats.error( - `Error: Bad response code ${ response.status() }.` - ) - ); + const response = await page.goto( urlObj.toString(), { + waitUntil: 'networkidle0', + } ); + if ( scriptTag ) { + await page.addScriptTag( { content: scriptTag, type: 'module' } ); } - continue; - } - completeRequests++; + if ( response.status() !== 200 ) { + if ( logProgress ) { + log( + formats.error( + `Error: Bad response code ${ response.status() }.` + ) + ); + } + continue; + } - if ( groupedMetrics.webVitals ) { - await Promise.all( - Object.values( groupedMetrics.webVitals ).map( - async ( value ) => { - // Wait until global is populated. - await page.waitForFunction( - `window.${ value.global } !== undefined` - ); + completeRequests++; - /* - * Do a random click, since only that triggers certain metrics - * like LCP, as only a user interaction stops reporting new LCP - * entries. See https://web.dev/lcp/. - * - * Click off screen to prevent clicking a link by accident and navigating away. - */ - await page.click( 'body', { - offset: { x: -500, y: -500 }, - } ); - // Get the metric value from the global. - const metric = - /** @type {number} */ await page.evaluate( - ( global ) => window[ global ], - value.global + if ( groupedMetrics.webVitals ) { + await Promise.all( + Object.values( groupedMetrics.webVitals ).map( + async ( value ) => { + // Wait until global is populated. + await page.waitForFunction( + `window.${ value.global } !== undefined` ); - value.results.push( metric ); - } - ) - ).catch( () => { - /* Ignore errors. */ - } ); - } - if ( groupedMetrics.serverTiming ) { - const serverTimingMetrics = await page.evaluate( () => { - const entry = performance.getEntries().find( - ( ent ) => ent instanceof PerformanceNavigationTiming // eslint-disable-line no-undef - ); - // eslint-disable-next-line no-undef - if ( entry instanceof PerformanceNavigationTiming ) { - return entry.serverTiming.reduce( ( acc, value ) => { - acc[ value.name ] = value.duration; - return acc; - }, {} ); - } - return {}; - } ); - Object.values( groupedMetrics.serverTiming ).forEach( ( value ) => { - if ( serverTimingMetrics[ value.name ] ) { - value.results.push( serverTimingMetrics[ value.name ] ); - } - } ); - } + /* + * Do a random click, since only that triggers certain metrics + * like LCP, as only a user interaction stops reporting new LCP + * entries. See https://web.dev/lcp/. + * + * Click off screen to prevent clicking a link by accident and navigating away. + */ + await page.click( 'body', { + offset: { x: -500, y: -500 }, + } ); + // Get the metric value from the global. + const metric = + /** @type {number} */ await page.evaluate( + ( global ) => window[ global ], + value.global + ); + value.results.push( metric ); + } + ) + ).catch( () => { + /* Ignore errors. */ + } ); + } - if ( logProgress ) { - log( formats.success( 'Success.' ) ); + if ( groupedMetrics.serverTiming ) { + const serverTimingMetrics = await page.evaluate( () => { + const entry = performance.getEntries().find( + ( ent ) => ent instanceof PerformanceNavigationTiming // eslint-disable-line no-undef + ); + // eslint-disable-next-line no-undef + if ( entry instanceof PerformanceNavigationTiming ) { + return entry.serverTiming.reduce( ( acc, value ) => { + acc[ value.name ] = value.duration; + return acc; + }, {} ); + } + return {}; + } ); + Object.values( groupedMetrics.serverTiming ).forEach( ( value ) => { + if ( serverTimingMetrics[ value.name ] ) { + value.results.push( serverTimingMetrics[ value.name ] ); + } + } ); + } + + if ( logProgress ) { + log( formats.success( 'Success.' ) ); + } + } catch ( err ) { + log( formats.error( `Error: ${ err.message }.` ) ); } }