-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core(load-fast-4-pwa): use computed artifacts #4981
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,17 +11,14 @@ | |
* Afterwards, we report if the TTFI is less than 10 seconds. | ||
*/ | ||
|
||
const isDeepEqual = require('lodash.isequal'); | ||
const Audit = require('./audit'); | ||
const URL = require('../lib/url-shim'); | ||
const targetLatencyMs = require('../config/constants').throttling.mobile3G.rttMs; | ||
const Sentry = require('../lib/sentry'); | ||
const mobile3GThrottling = require('../config/constants').throttling.mobile3G; | ||
const Util = require('../report/v2/renderer/util.js'); | ||
|
||
// Maximum TTFI to be considered "fast" for PWA baseline checklist | ||
// Maximum TTI to be considered "fast" for PWA baseline checklist | ||
// https://developers.google.com/web/progressive-web-apps/checklist | ||
const MAXIMUM_TTFI = 10 * 1000; | ||
|
||
const WHITELISTED_STATUS_CODES = [307]; | ||
const MAXIMUM_TTI = 10 * 1000; | ||
|
||
class LoadFastEnough4Pwa extends Audit { | ||
/** | ||
|
@@ -32,116 +29,43 @@ class LoadFastEnough4Pwa extends Audit { | |
name: 'load-fast-enough-for-pwa', | ||
description: 'Page load is fast enough on 3G', | ||
failureDescription: 'Page load is not fast enough on 3G', | ||
helpText: 'A fast page load over a 3G network ensures a good mobile user experience. ' + | ||
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).', | ||
helpText: | ||
'A fast page load over a 3G network ensures a good mobile user experience. ' + | ||
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).', | ||
requiredArtifacts: ['traces', 'devtoolsLogs'], | ||
}; | ||
} | ||
|
||
/** | ||
* @param {!Artifacts} artifacts | ||
* @return {!AuditResult} | ||
* @param {LH.Artifacts} artifacts | ||
* @param {LH.Audit.Context} context | ||
* @return {LH.AuditResult} | ||
*/ | ||
static audit(artifacts) { | ||
const devtoolsLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; | ||
return artifacts.requestNetworkRecords(devtoolsLogs).then(networkRecords => { | ||
const firstRequestLatenciesByOrigin = new Map(); | ||
networkRecords.forEach(record => { | ||
// Ignore requests that don't have valid origin, timing data, came from the cache, were | ||
// redirected by Chrome without going to the network, or are not finished. | ||
const fromCache = record._fromDiskCache || record._fromMemoryCache; | ||
const origin = URL.getOrigin(record._url); | ||
if (!origin || !record._timing || fromCache || | ||
WHITELISTED_STATUS_CODES.includes(record.statusCode) || !record.finished) { | ||
return; | ||
} | ||
|
||
// Disregard requests with an invalid start time, (H2 request start times are sometimes less | ||
// than issue time and even negative which throws off timing) | ||
if (record._startTime < record._issueTime) { | ||
return; | ||
} | ||
|
||
// Use DevTools' definition of Waiting latency: https://github.com/ChromeDevTools/devtools-frontend/blob/66595b8a73a9c873ea7714205b828866630e9e82/front_end/network/RequestTimingView.js#L164 | ||
const latency = record._timing.receiveHeadersEnd - record._timing.sendEnd; | ||
const latencyInfo = { | ||
url: record._url, | ||
startTime: record._startTime, | ||
origin, | ||
latency, | ||
}; | ||
|
||
// Only examine the first request per origin to reduce noisiness from cases like H2 push | ||
// where individual request latency may not apply. | ||
const existing = firstRequestLatenciesByOrigin.get(origin); | ||
if (!existing || latencyInfo.startTime < existing.startTime) { | ||
firstRequestLatenciesByOrigin.set(origin, latencyInfo); | ||
} | ||
}); | ||
|
||
let firstRequestLatencies = Array.from(firstRequestLatenciesByOrigin.values()); | ||
const latency3gMin = targetLatencyMs - 10; | ||
const areLatenciesAll3G = firstRequestLatencies.every(val => val.latency > latency3gMin); | ||
firstRequestLatencies = firstRequestLatencies.map(item => ({ | ||
url: item.url, | ||
latency: Util.formatNumber(item.latency, 0.01), | ||
})); | ||
|
||
const trace = artifacts.traces[Audit.DEFAULT_PASS]; | ||
return artifacts.requestFirstInteractive(trace).then(firstInteractive => { | ||
const timeToFirstInteractive = firstInteractive.timeInMs; | ||
const isFast = timeToFirstInteractive < MAXIMUM_TTFI; | ||
|
||
const extendedInfo = { | ||
value: {areLatenciesAll3G, firstRequestLatencies, isFast, timeToFirstInteractive}, | ||
}; | ||
static async audit(artifacts, context) { | ||
const trace = artifacts.traces[Audit.DEFAULT_PASS]; | ||
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; | ||
const settingOverrides = {throttlingMethod: 'simulate', throttling: mobile3GThrottling}; | ||
const settings = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you drop a comment for this line? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah good call done |
||
context.settings.throttlingMethod !== 'provided' && | ||
isDeepEqual(context.settings.throttling, mobile3GThrottling) | ||
? context.settings | ||
: Object.assign({}, context.settings, settingOverrides); | ||
const metricComputationData = {trace, devtoolsLog, settings}; | ||
const tti = await artifacts.requestConsistentlyInteractive(metricComputationData); | ||
|
||
const score = Number(tti.timing <= MAXIMUM_TTI); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://developers.google.com/web/progressive-web-apps/checklist does say
let's change this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sg :) |
||
|
||
let debugString; | ||
if (!score) { | ||
// eslint-disable-next-line max-len | ||
debugString = `First Interactive was ${Util.formatMilliseconds(tti.timing)}. More details in the "Performance" section.`; | ||
} | ||
|
||
const details = Audit.makeTableDetails([ | ||
{key: 'url', itemType: 'url', text: 'URL'}, | ||
{key: 'latency', itemType: 'text', text: 'Latency (ms)'}, | ||
], firstRequestLatencies); | ||
|
||
if (!isFast) { | ||
return { | ||
rawValue: false, | ||
// eslint-disable-next-line max-len | ||
debugString: `First Interactive was at ${Util.formatMilliseconds(timeToFirstInteractive)}. More details in the "Performance" section.`, | ||
extendedInfo, | ||
}; | ||
} | ||
|
||
if (!areLatenciesAll3G) { | ||
const sentryContext = Sentry.getContext(); | ||
const hadThrottlingEnabled = sentryContext && sentryContext.extra && | ||
sentryContext.extra.networkThrottling; | ||
|
||
if (hadThrottlingEnabled) { | ||
// Track these instances in Sentry since there should be no requests that are fast when | ||
// throttling is enabled, and it's likely a throttling bug we should look into. | ||
const violatingLatency = firstRequestLatencies | ||
.find(item => Number(item.latency) < latency3gMin); | ||
Sentry.captureMessage('Network request latencies were not realistic', { | ||
tags: {audit: this.meta.name}, | ||
extra: {violatingLatency}, | ||
level: 'warning', | ||
}); | ||
} | ||
|
||
return { | ||
rawValue: true, | ||
// eslint-disable-next-line max-len | ||
debugString: `First Interactive was found at ${Util.formatMilliseconds(timeToFirstInteractive)}; however, the network request latencies were not sufficiently realistic, so the performance measurements cannot be trusted.`, | ||
extendedInfo, | ||
details, | ||
}; | ||
} | ||
|
||
return { | ||
rawValue: true, | ||
extendedInfo, | ||
}; | ||
}); | ||
}); | ||
return { | ||
score, | ||
debugString, | ||
rawValue: tti.timing, | ||
}; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to call out explicitly:
We're changing the PWA speed threshold from
TTFI <= 10s
to be a slightly more aggressiveTTI < 10s
.