chrome-devtools-frontend 1.0.1518653 → 1.0.1520139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/owner/COMMON_OWNERS +1 -2
- package/config/typescript/tsconfig.eslint.json +12 -1
- package/docs/ui_engineering.md +1011 -0
- package/eslint.config.mjs +1 -0
- package/front_end/core/host/GdpClient.ts +12 -3
- package/front_end/core/sdk/EnhancedTracesParser.ts +5 -5
- package/front_end/core/sdk/NetworkManager.ts +1 -0
- package/front_end/core/sdk/NetworkRequest.ts +10 -0
- package/front_end/core/sdk/RehydratingConnection.snapshot.txt +211 -0
- package/front_end/core/sdk/TargetManager.ts +4 -0
- package/front_end/entrypoints/main/MainImpl.ts +6 -1
- package/front_end/entrypoints/main/main-meta.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.js +19 -4
- package/front_end/models/ai_assistance/agents/AiAgent.ts +57 -10
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +64 -87
- package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -31
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +127 -29
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +106 -55
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +23 -19
- package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
- package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
- package/front_end/models/ai_assistance/performance/AIContext.ts +63 -8
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -0
- package/front_end/models/badges/AiExplorerBadge.ts +19 -3
- package/front_end/models/badges/Badge.ts +8 -1
- package/front_end/models/badges/CodeWhispererBadge.ts +1 -0
- package/front_end/models/badges/DOMDetectiveBadge.ts +1 -0
- package/front_end/models/badges/SpeedsterBadge.ts +1 -0
- package/front_end/models/badges/StarterBadge.ts +6 -0
- package/front_end/models/badges/badges.ts +1 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
- package/front_end/models/trace/EventsSerializer.ts +4 -3
- package/front_end/models/trace/handlers/UserInteractionsHandler.ts +101 -73
- package/front_end/models/trace/helpers/Timing.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +18 -8
- package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
- package/front_end/panels/ai_assistance/components/ChatView.ts +44 -68
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +63 -15
- package/front_end/panels/ai_assistance/components/chatView.css +12 -0
- package/front_end/panels/animation/AnimationTimeline.ts +1 -1
- package/front_end/panels/animation/animationTimeline.css +4 -0
- package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
- package/front_end/panels/common/BadgeNotification.ts +3 -3
- package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
- package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
- package/front_end/panels/console/ConsolePrompt.ts +6 -0
- package/front_end/panels/console/ConsoleView.ts +4 -2
- package/front_end/panels/coverage/CoverageListView.ts +133 -158
- package/front_end/panels/coverage/CoverageView.ts +39 -16
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
- package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
- package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
- package/front_end/panels/recorder/components/RecordingView.ts +2 -2
- package/front_end/panels/search/SearchResultsPane.ts +186 -134
- package/front_end/panels/search/SearchView.ts +42 -36
- package/front_end/panels/search/searchResultsPane.css +9 -0
- package/front_end/panels/search/searchView.css +0 -2
- package/front_end/panels/security/CookieControlsView.ts +2 -1
- package/front_end/panels/settings/AISettingsTab.ts +6 -3
- package/front_end/panels/settings/components/SyncSection.ts +26 -12
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -1
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -4
- package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/sourcesView.css +6 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
- package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
- package/front_end/panels/timeline/TimelinePanel.ts +2 -0
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +1 -1
- package/front_end/panels/timeline/components/NetworkRequestDetails.ts +1 -1
- package/front_end/panels/timeline/components/RelatedInsightChips.ts +1 -1
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +16 -25
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +19 -28
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +16 -25
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
- package/front_end/third_party/puppeteer/package/package.json +12 -4
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/Function.ts +22 -30
- package/front_end/tsconfig.json +12 -1
- package/front_end/ui/components/dialogs/Dialog.ts +1 -1
- package/front_end/ui/components/markdown_view/MarkdownImage.ts +4 -5
- package/front_end/ui/components/switch/SwitchImpl.ts +12 -1
- package/front_end/ui/components/text_editor/config.ts +16 -2
- package/front_end/ui/legacy/InspectorView.ts +86 -13
- package/front_end/ui/legacy/TabbedPane.ts +2 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -1
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -11
- package/front_end/ui/lit/i18n-template.ts +5 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +15 -5
- package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
- package/package.json +1 -1
@@ -2,8 +2,6 @@
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
|
-
import '../../../ui/components/icon_button/icon_button.js';
|
6
|
-
|
7
5
|
import * as Common from '../../../core/common/common.js';
|
8
6
|
import * as Host from '../../../core/host/host.js';
|
9
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
@@ -138,13 +136,23 @@ When referring to a trace event that has a corresponding \`eventKey\`, annotate
|
|
138
136
|
When asking the user to make a choice between multiple options, output a list of choices at the end of your text response. The format is \`SUGGESTIONS: ["suggestion1", "suggestion2", "suggestion3"]\`. This MUST start on a newline, and be a single line.
|
139
137
|
`;
|
140
138
|
|
139
|
+
const extraPreambleWhenFreshTrace = `Additional notes:
|
140
|
+
|
141
|
+
When referring to an element for which you know the nodeId, annotate your output using markdown link syntax:
|
142
|
+
- For example, if nodeId is 23: [LCP element](#node-23)
|
143
|
+
- This link will reveal the element in the Elements panel
|
144
|
+
- Never mention node or nodeId when referring to the element, and especially not in the link text.
|
145
|
+
- When referring to the LCP, it's useful to also mention what the LCP element is via its nodeId. Use the markdown link syntax to do so.
|
146
|
+
`;
|
147
|
+
|
141
148
|
const callFrameDataFormatDescription = `Each call frame is presented in the following format:
|
142
149
|
|
143
|
-
'id;name;duration;selfTime;urlIndex;childRange;[S]'
|
150
|
+
'id;eventKey;name;duration;selfTime;urlIndex;childRange;[S]'
|
144
151
|
|
145
152
|
Key definitions:
|
146
153
|
|
147
154
|
* id: A unique numerical identifier for the call frame. Never mention this id in the output to the user.
|
155
|
+
* eventKey: String that uniquely identifies this event in the flame chart.
|
148
156
|
* name: A concise string describing the call frame (e.g., 'Evaluate Script', 'render', 'fetchData').
|
149
157
|
* duration: The total execution time of the call frame, including its children.
|
150
158
|
* selfTime: The time spent directly within the call frame, excluding its children's execution.
|
@@ -154,11 +162,11 @@ Key definitions:
|
|
154
162
|
|
155
163
|
Example Call Tree:
|
156
164
|
|
157
|
-
1;main;500;100;;
|
158
|
-
2;update;200;50;;3
|
159
|
-
3;animate;150;20;0;4-5;S
|
160
|
-
4;calculatePosition;80;80;;
|
161
|
-
5;applyStyles;50;50;;
|
165
|
+
1;r-123;main;500;100;;
|
166
|
+
2;r-124;update;200;50;;3
|
167
|
+
3;p-49575-15428179-2834-374;animate;150;20;0;4-5;S
|
168
|
+
4;p-49575-15428179-3505-1162;calculatePosition;80;80;;
|
169
|
+
5;p-49575-15428179-5391-2767;applyStyles;50;50;;
|
162
170
|
`;
|
163
171
|
|
164
172
|
enum ScorePriority {
|
@@ -190,7 +198,7 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
190
198
|
}
|
191
199
|
|
192
200
|
override getOrigin(): string {
|
193
|
-
const {min, max} = this.#focus.
|
201
|
+
const {min, max} = this.#focus.parsedTrace.data.Meta.traceBounds;
|
194
202
|
return `trace-${min}-${max}`;
|
195
203
|
}
|
196
204
|
|
@@ -199,7 +207,7 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
199
207
|
}
|
200
208
|
|
201
209
|
override getTitle(): string {
|
202
|
-
const focus = this.#focus
|
210
|
+
const focus = this.#focus;
|
203
211
|
|
204
212
|
let url = focus.insightSet?.url;
|
205
213
|
if (!url) {
|
@@ -210,6 +218,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
210
218
|
if (focus.insight) {
|
211
219
|
parts.push(focus.insight.title);
|
212
220
|
}
|
221
|
+
if (focus.event) {
|
222
|
+
parts.push(Trace.Name.forEntry(focus.event));
|
223
|
+
}
|
213
224
|
if (focus.callTree) {
|
214
225
|
const node = focus.callTree.selectedNode ?? focus.callTree.rootNode;
|
215
226
|
parts.push(Trace.Name.forEntry(node.event));
|
@@ -222,9 +233,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
222
233
|
* "Ask AI".
|
223
234
|
*/
|
224
235
|
override async getSuggestions(): Promise<ConversationSuggestions|undefined> {
|
225
|
-
const
|
236
|
+
const focus = this.#focus;
|
226
237
|
|
227
|
-
if (
|
238
|
+
if (focus.callTree) {
|
228
239
|
return [
|
229
240
|
{title: 'What\'s the purpose of this work?', jslogContext: 'performance-default'},
|
230
241
|
{title: 'Where is time being spent?', jslogContext: 'performance-default'},
|
@@ -232,17 +243,17 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
232
243
|
];
|
233
244
|
}
|
234
245
|
|
235
|
-
if (
|
236
|
-
return new PerformanceInsightFormatter(
|
246
|
+
if (focus.insight) {
|
247
|
+
return new PerformanceInsightFormatter(focus, focus.insight).getSuggestions();
|
237
248
|
}
|
238
249
|
|
239
250
|
const suggestions: ConversationSuggestions =
|
240
251
|
[{title: 'What performance issues exist with my page?', jslogContext: 'performance-default'}];
|
241
252
|
|
242
|
-
if (
|
243
|
-
const lcp =
|
244
|
-
const cls =
|
245
|
-
const inp =
|
253
|
+
if (focus.insightSet) {
|
254
|
+
const lcp = focus.insightSet ? Trace.Insights.Common.getLCP(focus.insightSet) : null;
|
255
|
+
const cls = focus.insightSet ? Trace.Insights.Common.getCLS(focus.insightSet) : null;
|
256
|
+
const inp = focus.insightSet ? Trace.Insights.Common.getINP(focus.insightSet) : null;
|
246
257
|
|
247
258
|
const ModelHandlers = Trace.Handlers.ModelHandlers;
|
248
259
|
const GOOD = Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD;
|
@@ -259,9 +270,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
259
270
|
|
260
271
|
// Add up to 3 suggestions from the top failing insights.
|
261
272
|
const top3FailingInsightSuggestions =
|
262
|
-
Object.values(
|
273
|
+
Object.values(focus.insightSet.model)
|
263
274
|
.filter(model => model.state !== 'pass')
|
264
|
-
.map(model => new PerformanceInsightFormatter(
|
275
|
+
.map(model => new PerformanceInsightFormatter(focus, model).getSuggestions().at(-1))
|
265
276
|
.filter(suggestion => !!suggestion)
|
266
277
|
.slice(0, 3);
|
267
278
|
suggestions.push(...top3FailingInsightSuggestions);
|
@@ -280,6 +291,7 @@ const MAX_FUNCTION_RESULT_BYTE_LENGTH = 16384 * 4;
|
|
280
291
|
*/
|
281
292
|
export class PerformanceAgent extends AiAgent<AgentFocus> {
|
282
293
|
#formatter: PerformanceTraceFormatter|null = null;
|
294
|
+
#lastEventForEnhancedQuery: Trace.Types.Events.Event|undefined;
|
283
295
|
#lastInsightForEnhancedQuery: Trace.Insights.Types.InsightModel|undefined;
|
284
296
|
#hasShownAnalyzeTraceContext = false;
|
285
297
|
|
@@ -300,6 +312,10 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
300
312
|
text: extraPreambleWhenNotExternal,
|
301
313
|
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
302
314
|
};
|
315
|
+
#freshTraceExtraPreambleFact: Host.AidaClient.RequestFact = {
|
316
|
+
text: extraPreambleWhenFreshTrace,
|
317
|
+
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
318
|
+
};
|
303
319
|
#networkDataDescriptionFact: Host.AidaClient.RequestFact = {
|
304
320
|
text: PerformanceTraceFormatter.networkDataFormatDescription,
|
305
321
|
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
@@ -373,10 +389,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
373
389
|
* 1. go to paulirish.com, record a trace
|
374
390
|
* 2. say "What performance issues exist with my page?"
|
375
391
|
* 3. then say "images"
|
376
|
-
*
|
377
|
-
* TODO(cjamcl): reduce the reliance on this by making sure all URL references
|
378
|
-
* (such as the insight formatters) add the "eventKey" as a suffix, just like all
|
379
|
-
* other events.
|
380
392
|
*/
|
381
393
|
#parseForKnownUrls(response: string): string {
|
382
394
|
const focus = this.context?.getItem();
|
@@ -405,8 +417,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
405
417
|
return match;
|
406
418
|
}
|
407
419
|
|
408
|
-
const request =
|
409
|
-
focus.data.parsedTrace.data.NetworkRequests.byTime.find(request => request.args.data.url === urlText);
|
420
|
+
const request = focus.parsedTrace.data.NetworkRequests.byTime.find(request => request.args.data.url === urlText);
|
410
421
|
if (!request) {
|
411
422
|
return match;
|
412
423
|
}
|
@@ -420,53 +431,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
420
431
|
});
|
421
432
|
}
|
422
433
|
|
423
|
-
#parseSuggestions(text: string): ParsedResponse {
|
424
|
-
if (!text) {
|
425
|
-
return {answer: ''};
|
426
|
-
}
|
427
|
-
|
428
|
-
const lines = text.split('\n');
|
429
|
-
const answerLines: string[] = [];
|
430
|
-
let suggestions: [string, ...string[]]|undefined;
|
431
|
-
|
432
|
-
for (const line of lines) {
|
433
|
-
const trimmed = line.trim();
|
434
|
-
if (trimmed.startsWith('SUGGESTIONS:')) {
|
435
|
-
try {
|
436
|
-
// TODO: Do basic validation this is an array with strings
|
437
|
-
suggestions = JSON.parse(trimmed.substring('SUGGESTIONS:'.length).trim());
|
438
|
-
} catch {
|
439
|
-
}
|
440
|
-
} else {
|
441
|
-
answerLines.push(line);
|
442
|
-
}
|
443
|
-
}
|
444
|
-
|
445
|
-
// Sometimes the model fails to put the SUGGESTIONS text on its own line. Handle
|
446
|
-
// the case where the suggestions are part of the last line of the answer.
|
447
|
-
if (!suggestions && answerLines.at(-1)?.includes('SUGGESTIONS:')) {
|
448
|
-
const [answer, suggestionsText] = answerLines[answerLines.length - 1].split('SUGGESTIONS:', 2);
|
449
|
-
try {
|
450
|
-
// TODO: Do basic validation this is an array with strings
|
451
|
-
suggestions = JSON.parse(suggestionsText.trim().substring('SUGGESTIONS:'.length).trim());
|
452
|
-
} catch {
|
453
|
-
}
|
454
|
-
answerLines[answerLines.length - 1] = answer;
|
455
|
-
}
|
456
|
-
|
457
|
-
const response: ParsedResponse = {
|
458
|
-
// If we could not parse the parts, consider the response to be an
|
459
|
-
// answer.
|
460
|
-
answer: answerLines.join('\n'),
|
461
|
-
};
|
462
|
-
|
463
|
-
if (suggestions) {
|
464
|
-
response.suggestions = suggestions;
|
465
|
-
}
|
466
|
-
|
467
|
-
return response;
|
468
|
-
}
|
469
|
-
|
470
434
|
#parseMarkdown(response: string): string {
|
471
435
|
/**
|
472
436
|
* Sometimes the LLM responds with code chunks that wrap a text based markdown response.
|
@@ -482,10 +446,10 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
482
446
|
}
|
483
447
|
|
484
448
|
override parseTextResponse(response: string): ParsedResponse {
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
return
|
449
|
+
const parsedResponse = super.parseTextResponse(response);
|
450
|
+
parsedResponse.answer = this.#parseForKnownUrls(parsedResponse.answer);
|
451
|
+
parsedResponse.answer = this.#parseMarkdown(parsedResponse.answer);
|
452
|
+
return parsedResponse;
|
489
453
|
}
|
490
454
|
|
491
455
|
override async enhanceQuery(query: string, context: PerformanceTraceContext|null): Promise<string> {
|
@@ -500,13 +464,21 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
500
464
|
const focus = context.getItem();
|
501
465
|
const selected: string[] = [];
|
502
466
|
|
503
|
-
if (focus.
|
467
|
+
if (focus.event) {
|
468
|
+
const includeEventInfo = focus.event !== this.#lastEventForEnhancedQuery;
|
469
|
+
this.#lastEventForEnhancedQuery = focus.event;
|
470
|
+
if (includeEventInfo) {
|
471
|
+
selected.push(`User selected an event ${this.#formatter?.serializeEvent(focus.event)}.\n\n`);
|
472
|
+
}
|
473
|
+
}
|
474
|
+
|
475
|
+
if (focus.callTree) {
|
504
476
|
// If this is a followup chat about the same call tree, don't include the call tree serialization again.
|
505
477
|
// We don't need to repeat it and we'd rather have more the context window space.
|
506
478
|
let contextString = '';
|
507
|
-
if (!this.#callTreeContextSet.has(focus.
|
508
|
-
contextString = focus.
|
509
|
-
this.#callTreeContextSet.add(focus.
|
479
|
+
if (!this.#callTreeContextSet.has(focus.callTree)) {
|
480
|
+
contextString = focus.callTree.serialize();
|
481
|
+
this.#callTreeContextSet.add(focus.callTree);
|
510
482
|
}
|
511
483
|
|
512
484
|
if (contextString) {
|
@@ -514,17 +486,17 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
514
486
|
}
|
515
487
|
}
|
516
488
|
|
517
|
-
if (focus.
|
489
|
+
if (focus.insight) {
|
518
490
|
// We only need to add Insight info to a prompt when the context changes. For example:
|
519
491
|
// User clicks Insight A. We need to send info on Insight A with the prompt.
|
520
492
|
// User asks follow up question. We do not need to resend Insight A with the prompt.
|
521
493
|
// User clicks Insight B. We now need to send info on Insight B with the prompt.
|
522
494
|
// User clicks Insight A. We should resend the Insight info with the prompt.
|
523
|
-
const includeInsightInfo = focus.
|
524
|
-
this.#lastInsightForEnhancedQuery = focus.
|
495
|
+
const includeInsightInfo = focus.insight !== this.#lastInsightForEnhancedQuery;
|
496
|
+
this.#lastInsightForEnhancedQuery = focus.insight;
|
525
497
|
|
526
498
|
if (includeInsightInfo) {
|
527
|
-
selected.push(`User selected the ${focus.
|
499
|
+
selected.push(`User selected the ${focus.insight.insightKey} insight.\n\n`);
|
528
500
|
}
|
529
501
|
}
|
530
502
|
|
@@ -636,11 +608,16 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
636
608
|
this.addFact(this.#notExternalExtraPreambleFact);
|
637
609
|
}
|
638
610
|
|
611
|
+
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(focus.parsedTrace);
|
612
|
+
if (isFresh) {
|
613
|
+
this.addFact(this.#freshTraceExtraPreambleFact);
|
614
|
+
}
|
615
|
+
|
639
616
|
this.addFact(this.#callFrameDataDescriptionFact);
|
640
617
|
this.addFact(this.#networkDataDescriptionFact);
|
641
618
|
|
642
619
|
if (!this.#traceFacts.length) {
|
643
|
-
this.#formatter = new PerformanceTraceFormatter(focus);
|
620
|
+
this.#formatter = new PerformanceTraceFormatter(focus, PerformanceInsightFormatter.create);
|
644
621
|
this.#createFactForTraceSummary();
|
645
622
|
this.#createFactForCriticalRequests();
|
646
623
|
this.#createFactForMainThreadBottomUpSummary();
|
@@ -672,7 +649,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
672
649
|
|
673
650
|
#declareFunctions(context: PerformanceTraceContext): void {
|
674
651
|
const focus = context.getItem();
|
675
|
-
const {parsedTrace, insightSet} = focus
|
652
|
+
const {parsedTrace, insightSet} = focus;
|
676
653
|
|
677
654
|
this.declareFunction<{insightName: string}, {details: string}>('getInsightDetails', {
|
678
655
|
description:
|
@@ -116,11 +116,11 @@ export class PerformanceAnnotationsAgent extends AiAgent<AgentFocus> {
|
|
116
116
|
}
|
117
117
|
|
118
118
|
const focus = context.getItem();
|
119
|
-
if (!focus.
|
119
|
+
if (!focus.callTree) {
|
120
120
|
throw new Error('unexpected context');
|
121
121
|
}
|
122
122
|
|
123
|
-
const callTree = focus.
|
123
|
+
const callTree = focus.callTree;
|
124
124
|
|
125
125
|
yield {
|
126
126
|
type: ResponseType.CONTEXT,
|
@@ -140,11 +140,11 @@ export class PerformanceAnnotationsAgent extends AiAgent<AgentFocus> {
|
|
140
140
|
}
|
141
141
|
|
142
142
|
const focus = context.getItem();
|
143
|
-
if (!focus.
|
143
|
+
if (!focus.callTree) {
|
144
144
|
throw new Error('unexpected context');
|
145
145
|
}
|
146
146
|
|
147
|
-
const callTree = focus.
|
147
|
+
const callTree = focus.callTree;
|
148
148
|
const contextString = callTree.serialize();
|
149
149
|
return `${contextString}\n\n# User request\n\n${query}`;
|
150
150
|
}
|
@@ -21,7 +21,6 @@ import {
|
|
21
21
|
type ConversationSuggestions,
|
22
22
|
type FunctionCallHandlerResult,
|
23
23
|
MultimodalInputType,
|
24
|
-
type ParsedResponse,
|
25
24
|
type RequestOptions,
|
26
25
|
ResponseType,
|
27
26
|
} from './AiAgent.js';
|
@@ -265,36 +264,6 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
265
264
|
override preambleFeatures(): string[] {
|
266
265
|
return ['function_calling'];
|
267
266
|
}
|
268
|
-
override parseTextResponse(text: string): ParsedResponse {
|
269
|
-
// We're returning an empty answer to denote the erroneous case.
|
270
|
-
if (!text.trim()) {
|
271
|
-
return {answer: ''};
|
272
|
-
}
|
273
|
-
|
274
|
-
const lines = text.split('\n');
|
275
|
-
const answerLines: string[] = [];
|
276
|
-
let suggestions: [string, ...string[]]|undefined;
|
277
|
-
|
278
|
-
for (const line of lines) {
|
279
|
-
const trimmed = line.trim();
|
280
|
-
if (trimmed.startsWith('SUGGESTIONS:')) {
|
281
|
-
try {
|
282
|
-
// TODO: Do basic validation this is an array with strings
|
283
|
-
suggestions = JSON.parse(trimmed.substring('SUGGESTIONS:'.length).trim());
|
284
|
-
} catch {
|
285
|
-
}
|
286
|
-
} else {
|
287
|
-
answerLines.push(line);
|
288
|
-
}
|
289
|
-
}
|
290
|
-
|
291
|
-
return {
|
292
|
-
// If we could not parse the parts, consider the response to be an
|
293
|
-
// answer.
|
294
|
-
answer: answerLines.join('\n'),
|
295
|
-
suggestions,
|
296
|
-
};
|
297
|
-
}
|
298
267
|
|
299
268
|
#execJs: typeof executeJsCode;
|
300
269
|
|
package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt
CHANGED
@@ -7,7 +7,7 @@ This insight is used to analyze the time spent that contributed to the final LCP
|
|
7
7
|
|
8
8
|
## Detailed analysis:
|
9
9
|
The Largest Contentful Paint (LCP) time for this navigation was 240 ms.
|
10
|
-
The LCP element (IMG) is an image fetched from
|
10
|
+
The LCP element (IMG, nodeId: 23) is an image fetched from https://creativetouchrotherham.co.uk/images/creative-touch-home/creative_touch_rotherham_homehero/creative_touch_rotherham_homehero_700.webp (eventKey: s-1418).
|
11
11
|
## LCP resource network request: https://creativetouchrotherham.co.uk/images/creative-touch-home/creative_touch_rotherham_homehero/creative_touch_rotherham_homehero_700.webp
|
12
12
|
eventKey: s-1418
|
13
13
|
Timings:
|
@@ -68,7 +68,7 @@ This insight is used to analyze the time spent that contributed to the final LCP
|
|
68
68
|
|
69
69
|
## Detailed analysis:
|
70
70
|
The Largest Contentful Paint (LCP) time for this navigation was 129 ms.
|
71
|
-
The LCP element is an image fetched from
|
71
|
+
The LCP element is an image fetched from https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg (eventKey: s-1314).
|
72
72
|
## LCP resource network request: https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg
|
73
73
|
eventKey: s-1314
|
74
74
|
Timings:
|
@@ -186,7 +186,7 @@ It is important that all of these checks pass to minimize the delay between the
|
|
186
186
|
|
187
187
|
## Detailed analysis:
|
188
188
|
The Largest Contentful Paint (LCP) time for this navigation was 1,077 ms.
|
189
|
-
The LCP element is an image fetched from
|
189
|
+
The LCP element is an image fetched from http://localhost:8787/lcp-discovery-delay/lcp-image.jpg (eventKey: s-25281).
|
190
190
|
## LCP resource network request: http://localhost:8787/lcp-discovery-delay/lcp-image.jpg
|
191
191
|
eventKey: s-25281
|
192
192
|
Timings:
|
@@ -310,7 +310,7 @@ Layout shifts in this cluster:
|
|
310
310
|
- Start time: 472 ms
|
311
311
|
- Score: 0.0003
|
312
312
|
- Potential root causes:
|
313
|
-
- A font that was loaded over the network
|
313
|
+
- A font that was loaded over the network: https://fonts.gstatic.com/s/specialgothicexpandedone/v2/IurO6Zxk74-YaYk1r3HOet4g75ENmBxUmOK61tA0Iu5QmJF_.woff2 (eventKey: s-1158).
|
314
314
|
### Layout shift 2:
|
315
315
|
- Start time: 857 ms
|
316
316
|
- Score: 0.0844
|
@@ -320,12 +320,12 @@ Layout shifts in this cluster:
|
|
320
320
|
- Start time: 1,352 ms
|
321
321
|
- Score: 0.0068
|
322
322
|
- Potential root causes:
|
323
|
-
- An unsized image (IMG) (url: http://localhost:8000/unsized-image.png).
|
323
|
+
- An unsized image (IMG) (url: http://localhost:8000/unsized-image.png (eventKey: s-4487)).
|
324
324
|
### Layout shift 4:
|
325
325
|
- Start time: 1,537 ms
|
326
326
|
- Score: 0.3344
|
327
327
|
- Potential root causes:
|
328
|
-
- An unsized image (IMG) (url: http://localhost:8000/unsized-image.png).
|
328
|
+
- An unsized image (IMG) (url: http://localhost:8000/unsized-image.png (eventKey: s-4487)).
|
329
329
|
### Layout shift 5:
|
330
330
|
- Start time: 2,343 ms
|
331
331
|
- Score: 0.3396
|
@@ -338,6 +338,104 @@ Layout shifts in this cluster:
|
|
338
338
|
- https://web.dev/articles/optimize-cls
|
339
339
|
=== end content
|
340
340
|
|
341
|
+
Title: PerformanceInsightFormatter CLS serializes correctly when there are no layout shifts
|
342
|
+
Content:
|
343
|
+
## Insight Title: Layout shift culprits
|
344
|
+
|
345
|
+
## Insight Summary:
|
346
|
+
Cumulative Layout Shifts (CLS) is a measure of the largest burst of layout shifts for every unexpected layout shift that occurs during the lifecycle of a page. This is a Core Web Vital and the thresholds for categorizing a score are:
|
347
|
+
- Good: 0.1 or less
|
348
|
+
- Needs improvement: more than 0.1 and less than or equal to 0.25
|
349
|
+
- Bad: over 0.25
|
350
|
+
|
351
|
+
## Detailed analysis:
|
352
|
+
No layout shifts were found.
|
353
|
+
|
354
|
+
## Estimated savings: none
|
355
|
+
|
356
|
+
## External resources:
|
357
|
+
- https://wdeb.dev/articles/cls
|
358
|
+
- https://web.dev/articles/optimize-cls
|
359
|
+
=== end content
|
360
|
+
|
361
|
+
Title: PerformanceInsightFormatter CLS outputs information on non-composited animations
|
362
|
+
Content:
|
363
|
+
## Insight Title: Layout shift culprits
|
364
|
+
|
365
|
+
## Insight Summary:
|
366
|
+
Cumulative Layout Shifts (CLS) is a measure of the largest burst of layout shifts for every unexpected layout shift that occurs during the lifecycle of a page. This is a Core Web Vital and the thresholds for categorizing a score are:
|
367
|
+
- Good: 0.1 or less
|
368
|
+
- Needs improvement: more than 0.1 and less than or equal to 0.25
|
369
|
+
- Bad: over 0.25
|
370
|
+
|
371
|
+
## Detailed analysis:
|
372
|
+
The worst layout shift cluster was the cluster that started at 60 ms and ended at 1,243 ms, with a duration of 1,183 ms.
|
373
|
+
The score for this cluster is 0.0140.
|
374
|
+
|
375
|
+
Layout shifts in this cluster:
|
376
|
+
### Layout shift 1:
|
377
|
+
- Start time: 60 ms
|
378
|
+
- Score: 0.0012
|
379
|
+
- No potential root causes identified
|
380
|
+
### Layout shift 2:
|
381
|
+
- Start time: 76 ms
|
382
|
+
- Score: 0.0012
|
383
|
+
- No potential root causes identified
|
384
|
+
### Layout shift 3:
|
385
|
+
- Start time: 93 ms
|
386
|
+
- Score: 0.0012
|
387
|
+
- No potential root causes identified
|
388
|
+
### Layout shift 4:
|
389
|
+
- Start time: 110 ms
|
390
|
+
- Score: 0.0012
|
391
|
+
- No potential root causes identified
|
392
|
+
### Layout shift 5:
|
393
|
+
- Start time: 126 ms
|
394
|
+
- Score: 0.0012
|
395
|
+
- No potential root causes identified
|
396
|
+
### Layout shift 6:
|
397
|
+
- Start time: 143 ms
|
398
|
+
- Score: 0.0012
|
399
|
+
- No potential root causes identified
|
400
|
+
### Layout shift 7:
|
401
|
+
- Start time: 160 ms
|
402
|
+
- Score: 0.0012
|
403
|
+
- No potential root causes identified
|
404
|
+
### Layout shift 8:
|
405
|
+
- Start time: 176 ms
|
406
|
+
- Score: 0.0012
|
407
|
+
- No potential root causes identified
|
408
|
+
### Layout shift 9:
|
409
|
+
- Start time: 193 ms
|
410
|
+
- Score: 0.0012
|
411
|
+
- No potential root causes identified
|
412
|
+
### Layout shift 10:
|
413
|
+
- Start time: 210 ms
|
414
|
+
- Score: 0.0012
|
415
|
+
- No potential root causes identified
|
416
|
+
### Layout shift 11:
|
417
|
+
- Start time: 226 ms
|
418
|
+
- Score: 0.0012
|
419
|
+
- No potential root causes identified
|
420
|
+
### Layout shift 12:
|
421
|
+
- Start time: 243 ms
|
422
|
+
- Score: 0.0012
|
423
|
+
- Potential root causes:
|
424
|
+
- A non-composited animation:
|
425
|
+
- non-composited animation: `change-height`
|
426
|
+
Animation name: change-height
|
427
|
+
Unsupported CSS properties:
|
428
|
+
- height
|
429
|
+
Failure reasons:
|
430
|
+
- TARGET_HAS_INVALID_COMPOSITING_STATE, UNSUPPORTED_CSS_PROPERTY
|
431
|
+
|
432
|
+
## Estimated savings: none
|
433
|
+
|
434
|
+
## External resources:
|
435
|
+
- https://wdeb.dev/articles/cls
|
436
|
+
- https://web.dev/articles/optimize-cls
|
437
|
+
=== end content
|
438
|
+
|
341
439
|
Title: PerformanceInsightFormatter INP breakdown serializes the correct details
|
342
440
|
Content:
|
343
441
|
## Insight Title: INP breakdown
|
@@ -589,16 +687,16 @@ Total legacy JavaScript: 8 files.
|
|
589
687
|
|
590
688
|
Legacy JavaScript by file:
|
591
689
|
|
592
|
-
- Script: https://s.yimg.com/aaq/benji/benji-2.2.99.js - Wasted bytes: 37204 bytes
|
690
|
+
- Script: https://s.yimg.com/aaq/benji/benji-2.2.99.js (eventKey: s-3387) - Wasted bytes: 37204 bytes
|
593
691
|
Matches:
|
594
692
|
Line: 0, Column: 133, Name: Promise.allSettled
|
595
693
|
|
596
|
-
- Script: https://s.yimg.com/aaq/c/25fa214.caas-news_web.min.js - Wasted bytes: 36084 bytes
|
694
|
+
- Script: https://s.yimg.com/aaq/c/25fa214.caas-news_web.min.js (eventKey: s-3412) - Wasted bytes: 36084 bytes
|
597
695
|
Matches:
|
598
696
|
Line: 0, Column: 13310, Name: Array.from
|
599
697
|
Line: 0, Column: 14623, Name: Object.assign
|
600
698
|
|
601
|
-
- Script: https://s.yimg.com/du/ay/wnsrvbjmeprtfrnfx.js - Wasted bytes: 12850 bytes
|
699
|
+
- Script: https://s.yimg.com/du/ay/wnsrvbjmeprtfrnfx.js (eventKey: s-6273) - Wasted bytes: 12850 bytes
|
602
700
|
Matches:
|
603
701
|
Line: 111, Column: 7829, Name: @babel/plugin-transform-spread
|
604
702
|
Line: 111, Column: 1794, Name: Array.prototype.find
|
@@ -607,21 +705,21 @@ Line: 111, Column: 2748, Name: Object.values
|
|
607
705
|
Line: 111, Column: 2473, Name: String.prototype.includes
|
608
706
|
Line: 111, Column: 2627, Name: String.prototype.startsWith
|
609
707
|
|
610
|
-
- Script: https://static.criteo.net/js/ld/publishertag.prebid.144.js - Wasted bytes: 10751 bytes
|
708
|
+
- Script: https://static.criteo.net/js/ld/publishertag.prebid.144.js (eventKey: s-257378) - Wasted bytes: 10751 bytes
|
611
709
|
Matches:
|
612
710
|
Line: 1, Column: 74871, Name: Array.isArray
|
613
711
|
Line: 1, Column: 75344, Name: Array.prototype.filter
|
614
712
|
Line: 1, Column: 75013, Name: Array.prototype.indexOf
|
615
713
|
|
616
|
-
- Script: https://s.yimg.com/oa/consent.js - Wasted bytes: 8157 bytes
|
714
|
+
- Script: https://s.yimg.com/oa/consent.js (eventKey: s-3384) - Wasted bytes: 8157 bytes
|
617
715
|
Matches:
|
618
716
|
Line: 1, Column: 132267, Name: Array.prototype.includes
|
619
717
|
|
620
|
-
- Script: https://pm-widget.taboola.com/yahooweb-network/pmk-20220605.1.js - Wasted bytes: 7625 bytes
|
718
|
+
- Script: https://pm-widget.taboola.com/yahooweb-network/pmk-20220605.1.js (eventKey: s-52229) - Wasted bytes: 7625 bytes
|
621
719
|
Matches:
|
622
720
|
Line: 181, Column: 26, Name: Object.keys
|
623
721
|
|
624
|
-
- Script: https://news.yahoo.com/ - Wasted bytes: 7141 bytes
|
722
|
+
- Script: https://news.yahoo.com/ (eventKey: s-2116) - Wasted bytes: 7141 bytes
|
625
723
|
Matches:
|
626
724
|
Line: 0, Column: 8382, Name: @babel/plugin-transform-classes
|
627
725
|
Line: 0, Column: 107712, Name: Array.prototype.filter
|
@@ -629,7 +727,7 @@ Line: 0, Column: 107393, Name: Array.prototype.forEach
|
|
629
727
|
Line: 0, Column: 108005, Name: Array.prototype.map
|
630
728
|
Line: 0, Column: 108358, Name: String.prototype.includes
|
631
729
|
|
632
|
-
- Script: https://cdn.taboola.com/libtrc/yahooweb-network/loader.js - Wasted bytes: 7061 bytes
|
730
|
+
- Script: https://cdn.taboola.com/libtrc/yahooweb-network/loader.js (eventKey: s-6352) - Wasted bytes: 7061 bytes
|
633
731
|
Matches:
|
634
732
|
Line: 0, Column: 390544, Name: Object.entries
|
635
733
|
Line: 0, Column: 390688, Name: Object.values
|
@@ -669,12 +767,12 @@ This insight identifies font issues when a webpage uses custom fonts, for exampl
|
|
669
767
|
## Detailed analysis:
|
670
768
|
The following font display issues were found:
|
671
769
|
|
672
|
-
- Font name: jizaRExUiTo99u79D0KExcOPIDU.woff2, URL: https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2, Property 'font-display' set to: 'auto', Wasted time: 20 ms.
|
673
|
-
- Font name: SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2, URL: https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2, Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
674
|
-
- Font name: jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2, URL: https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2, Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
675
|
-
- Font name: SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2, URL: https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2, Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
676
|
-
- Font name: EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2, URL: https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2, Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
677
|
-
- Font name: S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2, URL: https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2, Property 'font-display' set to: 'auto', Wasted time: 10 ms.
|
770
|
+
- Font name: jizaRExUiTo99u79D0KExcOPIDU.woff2, URL: https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2 (eventKey: s-5246), Property 'font-display' set to: 'auto', Wasted time: 20 ms.
|
771
|
+
- Font name: SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2, URL: https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2 (eventKey: s-5232), Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
772
|
+
- Font name: jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2, URL: https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2 (eventKey: s-5259), Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
773
|
+
- Font name: SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2, URL: https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2 (eventKey: s-5269), Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
774
|
+
- Font name: EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2, URL: https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2 (eventKey: s-5325), Property 'font-display' set to: 'auto', Wasted time: 15 ms.
|
775
|
+
- Font name: S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2, URL: https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2 (eventKey: s-5238), Property 'font-display' set to: 'auto', Wasted time: 10 ms.
|
678
776
|
|
679
777
|
Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).
|
680
778
|
|
@@ -714,28 +812,28 @@ Total potential savings: 2 MB
|
|
714
812
|
|
715
813
|
The following images could be optimized:
|
716
814
|
|
717
|
-
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg
|
815
|
+
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg (eventKey: s-1212)
|
718
816
|
- Potential savings: 1.1 MB
|
719
817
|
- Optimizations:
|
720
818
|
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image's download size. (Est 1.1 MB)
|
721
819
|
|
722
|
-
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif
|
820
|
+
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif (eventKey: s-1216)
|
723
821
|
- Potential savings: 682 kB
|
724
822
|
- Optimizations:
|
725
823
|
Using video formats instead of GIFs can improve the download size of animated content. (Est 682 kB)
|
726
824
|
|
727
|
-
### https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png
|
825
|
+
### https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png (eventKey: s-1228)
|
728
826
|
- Potential savings: 176 kB
|
729
827
|
- Optimizations:
|
730
828
|
Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image's download size. (Est 134.1 kB)
|
731
829
|
This image file is larger than it needs to be (640x436) for its displayed dimensions (200x136). Use responsive images to reduce the image download size. (Est 162.9 kB)
|
732
830
|
|
733
|
-
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp
|
831
|
+
### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp (eventKey: s-1224)
|
734
832
|
- Potential savings: 49.8 kB
|
735
833
|
- Optimizations:
|
736
834
|
Increasing the image compression factor could improve this image's download size. (Est 49.8 kB)
|
737
835
|
|
738
|
-
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp
|
836
|
+
### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp (eventKey: s-1226)
|
739
837
|
- Potential savings: 41.4 kB
|
740
838
|
- Optimizations:
|
741
839
|
This image file is larger than it needs to be (2048x1356) for its displayed dimensions (200x132). Use responsive images to reduce the image download size. (Est 41.4 kB)
|
@@ -852,9 +950,9 @@ The network dependency tree checks found one or more problems.
|
|
852
950
|
Max critical path latency is 5,015 ms
|
853
951
|
|
854
952
|
The following is the critical request chain:
|
855
|
-
- http://localhost:8787/lcp-iframes/index.html (5,006 ms) (longest chain)
|
856
|
-
- http://localhost:8787/lcp-iframes/app.js (5,015 ms) (longest chain)
|
857
|
-
- http://localhost:8787/lcp-iframes/app.css (5,010 ms)
|
953
|
+
- http://localhost:8787/lcp-iframes/index.html (eventKey: s-7103) (5,006 ms) (longest chain)
|
954
|
+
- http://localhost:8787/lcp-iframes/app.js (eventKey: s-7225) (5,015 ms) (longest chain)
|
955
|
+
- http://localhost:8787/lcp-iframes/app.css (eventKey: s-7213) (5,010 ms)
|
858
956
|
|
859
957
|
no origins were preconnected.
|
860
958
|
|
@@ -979,7 +1077,7 @@ This insight identifies static resources that are not cached effectively by the
|
|
979
1077
|
## Detailed analysis:
|
980
1078
|
The following resources were associated with ineffficient cache policies:
|
981
1079
|
|
982
|
-
- https://chromedevtools.github.io/performance-stories/lcp-large-image/app.css
|
1080
|
+
- https://chromedevtools.github.io/performance-stories/lcp-large-image/app.css (eventKey: s-1106)
|
983
1081
|
- Cache Time to Live (TTL): 600 seconds
|
984
1082
|
- Wasted bytes: 0 B
|
985
1083
|
|