Skip to content

Commit 5f2b73e

Browse files
khempeniusbrendankenny
authored andcommitted
core(lightwallet): add timing-budget audit (GoogleChrome#9901)
1 parent 14d62c2 commit 5f2b73e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+405
-301
lines changed

lighthouse-core/audits/performance-budget.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ const UIStrings = {
2222
=1 {1 request}
2323
other {# requests}
2424
}`,
25-
/** Label for a column in a data table; entries will be how much the quantity or size of network requests exceeded a predetermined budget.*/
26-
columnOverBudget: 'Over Budget',
2725
};
2826

2927
const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);
@@ -139,7 +137,7 @@ class ResourceBudget extends Audit {
139137
{key: 'requestCount', itemType: 'numeric', text: str_(i18n.UIStrings.columnRequests)},
140138
{key: 'size', itemType: 'bytes', text: str_(i18n.UIStrings.columnTransferSize)},
141139
{key: 'countOverBudget', itemType: 'text', text: ''},
142-
{key: 'sizeOverBudget', itemType: 'bytes', text: str_(UIStrings.columnOverBudget)},
140+
{key: 'sizeOverBudget', itemType: 'bytes', text: str_(i18n.UIStrings.columnOverBudget)},
143141
];
144142

145143
return {
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* @license Copyright 2019 Google Inc. All Rights Reserved.
3+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5+
*/
6+
'use strict';
7+
8+
const Audit = require('./audit.js');
9+
const TimingSummary = require('../computed/metrics/timing-summary.js');
10+
const MainResource = require('../computed/main-resource.js');
11+
const Budget = require('../config/budget.js');
12+
const i18n = require('../lib/i18n/i18n.js');
13+
14+
const UIStrings = {
15+
/** Title of a Lighthouse audit that compares how quickly the page loads against targets set by the user. Timing budgets are a type of performance budget. */
16+
title: 'Timing budget',
17+
/** Description of a Lighthouse audit where a user sets budgets for how quickly the page loads. No character length limits. 'Learn More' becomes link text to additional documentation. */
18+
description: 'Set a timing budget to help you keep an eye on the performance of your site. Performant sites load fast and respond to user input events quickly. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).',
19+
/** Label for a column in a data table; entries will be the names of different timing metrics, e.g. "Time to Interactive", "First Contentful Paint", etc. */
20+
columnTimingMetric: 'Metric',
21+
/** Label for a column in a data table; entries will be the measured value of a particular timing metric. Most entries will have a unit of milliseconds, but units could be other things as well. */
22+
columnMeasurement: 'Measurement',
23+
};
24+
25+
const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);
26+
27+
/** @typedef {{metric: LH.Budget.TimingMetric, label: string, measurement?: number, overBudget?: number}} BudgetItem */
28+
29+
class TimingBudget extends Audit {
30+
/**
31+
* @return {LH.Audit.Meta}
32+
*/
33+
static get meta() {
34+
return {
35+
id: 'timing-budget',
36+
title: str_(UIStrings.title),
37+
description: str_(UIStrings.description),
38+
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
39+
requiredArtifacts: ['devtoolsLogs', 'traces', 'URL'],
40+
};
41+
}
42+
43+
/**
44+
* @param {LH.Budget.TimingMetric} timingMetric
45+
* @return {string}
46+
*/
47+
static getRowLabel(timingMetric) {
48+
/** @type {Record<LH.Budget.TimingMetric, string>} */
49+
const strMappings = {
50+
'first-contentful-paint': i18n.UIStrings.firstContentfulPaintMetric,
51+
'first-cpu-idle': i18n.UIStrings.firstCPUIdleMetric,
52+
'interactive': i18n.UIStrings.interactiveMetric,
53+
'first-meaningful-paint': i18n.UIStrings.firstMeaningfulPaintMetric,
54+
'max-potential-fid': i18n.UIStrings.maxPotentialFIDMetric,
55+
'estimated-input-latency': i18n.UIStrings.estimatedInputLatencyMetric,
56+
'total-blocking-time': i18n.UIStrings.totalBlockingTimeMetric,
57+
'speed-index': i18n.UIStrings.speedIndexMetric,
58+
};
59+
return str_(strMappings[timingMetric]);
60+
}
61+
62+
/**
63+
* @param {LH.Budget.TimingMetric} timingMetric
64+
* @param {LH.Artifacts.TimingSummary} summary
65+
* @return {number|undefined}
66+
*/
67+
static getMeasurement(timingMetric, summary) {
68+
/** @type {Record<LH.Budget.TimingMetric, number|undefined>} */
69+
const measurements = {
70+
'first-contentful-paint': summary.firstContentfulPaint,
71+
'first-cpu-idle': summary.firstCPUIdle,
72+
'interactive': summary.interactive,
73+
'first-meaningful-paint': summary.firstMeaningfulPaint,
74+
'max-potential-fid': summary.maxPotentialFID,
75+
'estimated-input-latency': summary.estimatedInputLatency,
76+
'total-blocking-time': summary.totalBlockingTime,
77+
'speed-index': summary.speedIndex,
78+
};
79+
return measurements[timingMetric];
80+
}
81+
82+
/**
83+
* @param {LH.Budget} budget
84+
* @param {LH.Artifacts.TimingSummary} summary
85+
* @return {Array<BudgetItem>}
86+
*/
87+
static tableItems(budget, summary) {
88+
if (!budget.timings) {
89+
return [];
90+
}
91+
return budget.timings.map((timingBudget) => {
92+
const metricName = timingBudget.metric;
93+
const label = this.getRowLabel(metricName);
94+
const measurement = this.getMeasurement(metricName, summary);
95+
const overBudget = measurement && (measurement > timingBudget.budget)
96+
? (measurement - timingBudget.budget) : undefined;
97+
return {
98+
metric: metricName,
99+
label,
100+
measurement,
101+
overBudget,
102+
};
103+
}).sort((a, b) => {
104+
return (b.overBudget || 0) - (a.overBudget || 0);
105+
});
106+
}
107+
108+
/**
109+
* @param {LH.Artifacts} artifacts
110+
* @param {LH.Audit.Context} context
111+
* @return {Promise<LH.Audit.Product>}
112+
*/
113+
static async audit(artifacts, context) {
114+
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
115+
const trace = artifacts.traces[Audit.DEFAULT_PASS];
116+
const mainResource = await MainResource.request({URL: artifacts.URL, devtoolsLog}, context);
117+
const summary = (await TimingSummary.request({trace, devtoolsLog}, context)).metrics;
118+
const budget = Budget.getMatchingBudget(context.settings.budgets, mainResource.url);
119+
120+
if (!budget) {
121+
return {
122+
score: 0,
123+
notApplicable: true,
124+
};
125+
}
126+
127+
/** @type {LH.Audit.Details.Table['headings']} */
128+
const headers = [
129+
{key: 'label', itemType: 'text', text: str_(UIStrings.columnTimingMetric)},
130+
/**
131+
* Note: SpeedIndex, unlike other timing metrics, is not measured in milliseconds.
132+
* The renderer applies the correct units to the 'measurement' and 'overBudget' columns for SpeedIndex.
133+
*/
134+
{key: 'measurement', itemType: 'ms', text: str_(UIStrings.columnMeasurement)},
135+
{key: 'overBudget', itemType: 'ms', text: str_(i18n.UIStrings.columnOverBudget)},
136+
];
137+
138+
return {
139+
details: Audit.makeTableDetails(headers, this.tableItems(budget, summary)),
140+
score: 1,
141+
};
142+
}
143+
}
144+
145+
module.exports = TimingBudget;
146+
module.exports.UIStrings = UIStrings;

lighthouse-core/computed/metrics/timing-summary.js

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const FirstCPUIdle = require('./first-cpu-idle.js');
1414
const Interactive = require('./interactive.js');
1515
const SpeedIndex = require('./speed-index.js');
1616
const EstimatedInputLatency = require('./estimated-input-latency.js');
17+
const MaxPotentialFID = require('./max-potential-fid.js');
1718
const TotalBlockingTime = require('./total-blocking-time.js');
1819
const makeComputedArtifact = require('../computed-artifact.js');
1920

@@ -44,6 +45,7 @@ class TimingSummary {
4445
const largestContentfulPaint = await requestOrUndefined(LargestContentfulPaint, metricComputationData); // eslint-disable-line max-len
4546
const firstCPUIdle = await requestOrUndefined(FirstCPUIdle, metricComputationData);
4647
const interactive = await requestOrUndefined(Interactive, metricComputationData);
48+
const maxPotentialFID = await requestOrUndefined(MaxPotentialFID, metricComputationData);
4749
const speedIndex = await requestOrUndefined(SpeedIndex, metricComputationData);
4850
const estimatedInputLatency = await EstimatedInputLatency.request(metricComputationData, context); // eslint-disable-line max-len
4951
const totalBlockingTime = await TotalBlockingTime.request(metricComputationData, context); // eslint-disable-line max-len
@@ -66,6 +68,7 @@ class TimingSummary {
6668
estimatedInputLatency: estimatedInputLatency.timing,
6769
estimatedInputLatencyTs: estimatedInputLatency.timestamp,
6870
totalBlockingTime: totalBlockingTime.timing,
71+
maxPotentialFID: maxPotentialFID && maxPotentialFID.timing,
6972

7073
// Include all timestamps of interest from trace of tab
7174
observedNavigationStart: traceOfTab.timings.navigationStart,

lighthouse-core/lib/i18n/i18n.js

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ const UIStrings = {
7676
columnTransferSize: 'Transfer Size',
7777
/** Label for a column in a data table; entries will be the names of arbitrary objects, e.g. the name of a Javascript library, or the name of a user defined timing event. */
7878
columnName: 'Name',
79+
/** Label for a column in a data table; entries will be how much a predetermined budget has been exeeded by. Depending on the context, this number could represent an excess in quantity or size of network requests, or, an excess in the duration of time that it takes for the page to load.*/
80+
columnOverBudget: 'Over Budget',
7981
/** Label for a row in a data table; entries will be the total number and byte size of all resources loaded by a web page. */
8082
totalResourceType: 'Total',
8183
/** Label for a row in a data table; entries will be the total number and byte size of all 'Document' resources loaded by a web page. */

lighthouse-core/lib/i18n/locales/ar-XB.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "‏‮Lighthouse‬‏ ‏‮couldn‬‏'‏‮t‬‏ ‏‮read‬‏ ‏‮the‬‏ `start_url` ‏‮from‬‏ ‏‮the‬‏ ‏‮manifest‬‏. ‏‮As‬‏ ‏‮a‬‏ ‏‮result‬‏, ‏‮the‬‏ `start_url` ‏‮was‬‏ ‏‮assumed‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮the‬‏ ‏‮document‬‏'‏‮s‬‏ ‏‮URL‬‏. ‏‮Error‬‏ ‏‮message‬‏: '{manifestWarning}'."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "‏‮Over‬‏ ‏‮Budget‬‏"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "‏‮Keep‬‏ ‏‮the‬‏ ‏‮quantity‬‏ ‏‮and‬‏ ‏‮size‬‏ ‏‮of‬‏ ‏‮network‬‏ ‏‮requests‬‏ ‏‮under‬‏ ‏‮the‬‏ ‏‮targets‬‏ ‏‮set‬‏ ‏‮by‬‏ ‏‮the‬‏ ‏‮provided‬‏ ‏‮performance‬‏ ‏‮budget‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "‏‮Server‬‏ ‏‮response‬‏ ‏‮times‬‏ ‏‮are‬‏ ‏‮low‬‏ (‏‮TTFB‬‏)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "‏‮Duration‬‏"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "‏‮Start‬‏ ‏‮Time‬‏"
10781072
},

lighthouse-core/lib/i18n/locales/ar.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "تعذّر على Lighthouse قراءة `start_url` من البيان. ونتيجة لذلك، كان من المفترض أن يكون `start_url` هو عنوان URL للمستند. رسالة خطأ: '{manifestWarning}'."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "تجاوز الميزانية"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "يمكنك الحفاظ على كمية طلبات الشبكة وحجمها ضمن الاستهدافات المحدّدة في ميزانية الأداء المقدّمة. [مزيد من المعلومات](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "أوقات استجابة الخادم منخفضة (TTFB)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "المدة"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "وقت البدء"
10781072
},

lighthouse-core/lib/i18n/locales/bg.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Lighthouse не можа да прочете `start_url` от манифеста. В резултат на това бе предположено, че URL адресът на документа изпълнява функцията на `start_url`. Съобщение за грешка: „{manifestWarning}“."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Надхвърля бюджета"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Поддържайте количеството и обема на мрежовите заявки под целевите стойности в посочения бюджет за ефективността. [Научете повече](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Сървърът отговаря бързо (време до първия байт)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Продължителност"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Начален час"
10781072
},

lighthouse-core/lib/i18n/locales/ca.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Lighthouse no ha pogut llegir l'atribut `start_url` del fitxer de manifest, de manera que s'ha donat per fet que `start_url` era l'URL del document. Missatge d'error: \"{manifestWarning}\"."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Per sobre del pressupost"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Manté la quantitat i la mida de les sol·licituds de xarxa ajustades als objectius establerts al pressupost de rendiment que s'ha proporcionat. [Obtén més informació](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Els temps de resposta del servidor són baixos (TTFB)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Durada"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Hora d'inici"
10781072
},

lighthouse-core/lib/i18n/locales/cs.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Nástroji Lighthouse se v manifestu nepodařilo přečíst atribut `start_url`. Proto se předpokládá, že adresou URL dokumentu je `start_url`. Chybová zpráva: {manifestWarning}"
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Nad rozpočet"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Udržujte množství a velikost síťových požadavků pod cílovými hodnotami, které udává poskytnutý rozpočet výkonu. [Další informace](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Doby odezvy serveru jsou krátké (TTFB)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Trvání"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Čas zahájení"
10781072
},

lighthouse-core/lib/i18n/locales/da.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Lighthouse kunne ikke læse `start_url` fra manifestet. `start_url` blev derfor betragtet som dokumentets webadresse. Fejlmeddelelse: \"{manifestWarning}\"."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Over budget"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Sørg for, at antallet af og størrelsen på netværksanmodningerne ikke overskrider målene i det angivne budget for ydeevne. [Få flere oplysninger](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Serversvartiderne er korte (TTFB, Time To First Byte)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Varighed"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Starttidspunkt"
10781072
},

lighthouse-core/lib/i18n/locales/de.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Lighthouse konnte die `start_url` nicht im Manifest abrufen. Daher wurde angenommen, dass es sich bei der `start_url` um die URL des Dokuments handelt. Fehlermeldung: \"{manifestWarning}\"."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Über dem Budget"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Die Anzahl und Größe der Netzwerkanfragen sollten unter den Zielvorgaben des Leistungsbudgets liegen. [Weitere Informationen.](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Serverantwortzeiten sind niedrig (TTFB)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Dauer"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Beginn"
10781072
},

lighthouse-core/lib/i18n/locales/el.json

-6
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,6 @@
815815
"lighthouse-core/audits/offline-start-url.js | warningCantStart": {
816816
"message": "Το Lighthouse δεν μπόρεσε να διαβάσει το `start_url` από το μανιφέστο. Επομένως, το `start_url` θεωρήθηκε ότι είναι το URL του εγγράφου. Μήνυμα σφάλματος: '{manifestWarning}'."
817817
},
818-
"lighthouse-core/audits/performance-budget.js | columnOverBudget": {
819-
"message": "Υπέρβαση προϋπολογισμού"
820-
},
821818
"lighthouse-core/audits/performance-budget.js | description": {
822819
"message": "Διατηρήστε την ποσότητα και το μέγεθος των αιτημάτων δικτύου εντός των στόχων που ορίζονται από τον παρεχόμενο προϋπολογισμό απόδοσης. [Μάθετε περισσότερα](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
823820
},
@@ -1070,9 +1067,6 @@
10701067
"lighthouse-core/audits/time-to-first-byte.js | title": {
10711068
"message": "Οι χρόνοι απόκρισης διακομιστή είναι χαμηλοί (TTFB)"
10721069
},
1073-
"lighthouse-core/audits/user-timings.js | columnDuration": {
1074-
"message": "Διάρκεια"
1075-
},
10761070
"lighthouse-core/audits/user-timings.js | columnStartTime": {
10771071
"message": "Ώρα έναρξης"
10781072
},

0 commit comments

Comments
 (0)