chrome-devtools-frontend 1.0.1519267 → 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/front_end/core/host/GdpClient.ts +12 -3
- package/front_end/core/sdk/NetworkManager.ts +1 -0
- package/front_end/core/sdk/NetworkRequest.ts +10 -0
- package/front_end/entrypoints/main/MainImpl.ts +6 -1
- package/front_end/entrypoints/main/main-meta.ts +3 -3
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +60 -34
- package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +127 -29
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +100 -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 +62 -7
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -5
- package/front_end/models/badges/Badge.ts +6 -1
- package/front_end/models/badges/StarterBadge.ts +5 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +5 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +14 -7
- 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 +47 -1
- 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/preloading/components/PreloadingString.ts +2 -5
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
- 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/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/search/SearchResultsPane.ts +48 -15
- package/front_end/panels/search/SearchView.ts +33 -30
- package/front_end/panels/search/searchView.css +0 -2
- package/front_end/panels/settings/components/SyncSection.ts +3 -3
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
- package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
- 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/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/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/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 +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +1 -1
- 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 +4 -4
- 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/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 +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +1 -1
- 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 +3 -2
- 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/PipeTransport.ts +15 -17
- package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/Function.ts +1 -1
- package/front_end/tsconfig.json +12 -1
- package/front_end/ui/legacy/InspectorView.ts +86 -13
- package/front_end/ui/legacy/TabbedPane.ts +2 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
- package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
- package/package.json +1 -1
@@ -68,6 +68,11 @@ export interface Profile {
|
|
68
68
|
};
|
69
69
|
}
|
70
70
|
|
71
|
+
interface InitializeResult {
|
72
|
+
hasProfile: boolean;
|
73
|
+
isEligible: boolean;
|
74
|
+
}
|
75
|
+
|
71
76
|
// The `batchGet` awards endpoint returns badge names with an
|
72
77
|
// obfuscated user ID (e.g., `profiles/12345/awards/badge-name`).
|
73
78
|
// This function normalizes them to use `me` instead of the ID
|
@@ -114,9 +119,13 @@ export class GdpClient {
|
|
114
119
|
return gdpClientInstance;
|
115
120
|
}
|
116
121
|
|
117
|
-
async initialize(): Promise<
|
118
|
-
|
119
|
-
|
122
|
+
async initialize(): Promise<InitializeResult> {
|
123
|
+
return await Promise.all([this.getProfile(), this.checkEligibility()]).then(([profile, eligibilityResponse]) => {
|
124
|
+
return {
|
125
|
+
hasProfile: Boolean(profile),
|
126
|
+
isEligible: eligibilityResponse?.createProfile === EligibilityStatus.ELIGIBLE
|
127
|
+
};
|
128
|
+
});
|
120
129
|
}
|
121
130
|
|
122
131
|
async getProfile(): Promise<Profile|null> {
|
@@ -597,6 +597,7 @@ export class NetworkDispatcher implements ProtocolProxyApi.NetworkDispatcher {
|
|
597
597
|
networkRequest.mixedContentType = request.mixedContentType || Protocol.Security.MixedContentType.None;
|
598
598
|
networkRequest.setReferrerPolicy(request.referrerPolicy);
|
599
599
|
networkRequest.setIsSameSite(request.isSameSite || false);
|
600
|
+
networkRequest.setIsAdRelated(request.isAdRelated || false);
|
600
601
|
}
|
601
602
|
|
602
603
|
private updateNetworkRequestWithResponse(networkRequest: NetworkRequest, response: Protocol.Network.Response): void {
|
@@ -320,6 +320,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
320
320
|
directSocketInfo?: DirectSocketInfo;
|
321
321
|
readonly #directSocketChunks: DirectSocketChunk[] = [];
|
322
322
|
#isIpProtectionUsed: boolean;
|
323
|
+
#isAdRelated: boolean;
|
323
324
|
|
324
325
|
constructor(
|
325
326
|
requestId: string,
|
@@ -342,6 +343,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
342
343
|
this.#initiator = initiator;
|
343
344
|
this.#hasUserGesture = hasUserGesture;
|
344
345
|
this.#isIpProtectionUsed = false;
|
346
|
+
this.#isAdRelated = false;
|
345
347
|
}
|
346
348
|
|
347
349
|
static create(
|
@@ -1850,6 +1852,14 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
1850
1852
|
return this.#isIpProtectionUsed;
|
1851
1853
|
}
|
1852
1854
|
|
1855
|
+
setIsAdRelated(isAdRelated: boolean): void {
|
1856
|
+
this.#isAdRelated = isAdRelated;
|
1857
|
+
}
|
1858
|
+
|
1859
|
+
isAdRelated(): boolean {
|
1860
|
+
return this.#isAdRelated;
|
1861
|
+
}
|
1862
|
+
|
1853
1863
|
getAssociatedData(key: string): object|null {
|
1854
1864
|
return this.#associatedData.get(key) || null;
|
1855
1865
|
}
|
@@ -519,7 +519,12 @@ export class MainImpl {
|
|
519
519
|
|
520
520
|
// Initialize `GDPClient` and `UserBadges` for Google Developer Program integration
|
521
521
|
if (Host.GdpClient.isGdpProfilesAvailable()) {
|
522
|
-
void Host.GdpClient.GdpClient.instance().initialize()
|
522
|
+
void Host.GdpClient.GdpClient.instance().initialize().then(({hasProfile, isEligible}) => {
|
523
|
+
const contextString = hasProfile ? 'has-profile' :
|
524
|
+
isEligible ? 'no-profile-and-eligible' :
|
525
|
+
'no-profile-and-not-eligible';
|
526
|
+
void VisualLogging.logFunctionCall('gdp-client-initialize', contextString);
|
527
|
+
});
|
523
528
|
void Badges.UserBadges.instance().initialize();
|
524
529
|
Badges.UserBadges.instance().addEventListener(Badges.Events.BADGE_TRIGGERED, async ev => {
|
525
530
|
loadedPanelCommonModule ??= await import('../../panels/common/common.js') as typeof PanelCommon;
|
@@ -188,9 +188,9 @@ const UIStrings = {
|
|
188
188
|
browserLanguage: 'Browser UI language',
|
189
189
|
/**
|
190
190
|
* @description Label for a checkbox in the settings UI. Allows developers to opt-in/opt-out
|
191
|
-
* of
|
191
|
+
* of saving settings to their Google account.
|
192
192
|
*/
|
193
|
-
|
193
|
+
saveSettings: 'Save `DevTools` settings to your `Google` account',
|
194
194
|
/**
|
195
195
|
* @description Label for a checkbox in the settings UI. Allows developers to opt-in/opt-out
|
196
196
|
* of receiving Google Developer Program (GDP) badges based on their activity in Chrome DevTools.
|
@@ -789,7 +789,7 @@ Common.Settings.registerSettingExtension({
|
|
789
789
|
// This name must be kept in sync with DevToolsSettings::kSyncDevToolsPreferencesFrontendName.
|
790
790
|
settingName: 'sync-preferences',
|
791
791
|
settingType: Common.Settings.SettingType.BOOLEAN,
|
792
|
-
title: i18nLazyString(UIStrings.
|
792
|
+
title: i18nLazyString(UIStrings.saveSettings),
|
793
793
|
defaultValue: false,
|
794
794
|
reloadRequired: true,
|
795
795
|
});
|
@@ -136,13 +136,23 @@ When referring to a trace event that has a corresponding \`eventKey\`, annotate
|
|
136
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.
|
137
137
|
`;
|
138
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
|
+
|
139
148
|
const callFrameDataFormatDescription = `Each call frame is presented in the following format:
|
140
149
|
|
141
|
-
'id;name;duration;selfTime;urlIndex;childRange;[S]'
|
150
|
+
'id;eventKey;name;duration;selfTime;urlIndex;childRange;[S]'
|
142
151
|
|
143
152
|
Key definitions:
|
144
153
|
|
145
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.
|
146
156
|
* name: A concise string describing the call frame (e.g., 'Evaluate Script', 'render', 'fetchData').
|
147
157
|
* duration: The total execution time of the call frame, including its children.
|
148
158
|
* selfTime: The time spent directly within the call frame, excluding its children's execution.
|
@@ -152,11 +162,11 @@ Key definitions:
|
|
152
162
|
|
153
163
|
Example Call Tree:
|
154
164
|
|
155
|
-
1;main;500;100;;
|
156
|
-
2;update;200;50;;3
|
157
|
-
3;animate;150;20;0;4-5;S
|
158
|
-
4;calculatePosition;80;80;;
|
159
|
-
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;;
|
160
170
|
`;
|
161
171
|
|
162
172
|
enum ScorePriority {
|
@@ -188,7 +198,7 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
188
198
|
}
|
189
199
|
|
190
200
|
override getOrigin(): string {
|
191
|
-
const {min, max} = this.#focus.
|
201
|
+
const {min, max} = this.#focus.parsedTrace.data.Meta.traceBounds;
|
192
202
|
return `trace-${min}-${max}`;
|
193
203
|
}
|
194
204
|
|
@@ -197,7 +207,7 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
197
207
|
}
|
198
208
|
|
199
209
|
override getTitle(): string {
|
200
|
-
const focus = this.#focus
|
210
|
+
const focus = this.#focus;
|
201
211
|
|
202
212
|
let url = focus.insightSet?.url;
|
203
213
|
if (!url) {
|
@@ -208,6 +218,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
208
218
|
if (focus.insight) {
|
209
219
|
parts.push(focus.insight.title);
|
210
220
|
}
|
221
|
+
if (focus.event) {
|
222
|
+
parts.push(Trace.Name.forEntry(focus.event));
|
223
|
+
}
|
211
224
|
if (focus.callTree) {
|
212
225
|
const node = focus.callTree.selectedNode ?? focus.callTree.rootNode;
|
213
226
|
parts.push(Trace.Name.forEntry(node.event));
|
@@ -220,9 +233,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
220
233
|
* "Ask AI".
|
221
234
|
*/
|
222
235
|
override async getSuggestions(): Promise<ConversationSuggestions|undefined> {
|
223
|
-
const
|
236
|
+
const focus = this.#focus;
|
224
237
|
|
225
|
-
if (
|
238
|
+
if (focus.callTree) {
|
226
239
|
return [
|
227
240
|
{title: 'What\'s the purpose of this work?', jslogContext: 'performance-default'},
|
228
241
|
{title: 'Where is time being spent?', jslogContext: 'performance-default'},
|
@@ -230,17 +243,17 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
230
243
|
];
|
231
244
|
}
|
232
245
|
|
233
|
-
if (
|
234
|
-
return new PerformanceInsightFormatter(
|
246
|
+
if (focus.insight) {
|
247
|
+
return new PerformanceInsightFormatter(focus, focus.insight).getSuggestions();
|
235
248
|
}
|
236
249
|
|
237
250
|
const suggestions: ConversationSuggestions =
|
238
251
|
[{title: 'What performance issues exist with my page?', jslogContext: 'performance-default'}];
|
239
252
|
|
240
|
-
if (
|
241
|
-
const lcp =
|
242
|
-
const cls =
|
243
|
-
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;
|
244
257
|
|
245
258
|
const ModelHandlers = Trace.Handlers.ModelHandlers;
|
246
259
|
const GOOD = Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD;
|
@@ -257,9 +270,9 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
257
270
|
|
258
271
|
// Add up to 3 suggestions from the top failing insights.
|
259
272
|
const top3FailingInsightSuggestions =
|
260
|
-
Object.values(
|
273
|
+
Object.values(focus.insightSet.model)
|
261
274
|
.filter(model => model.state !== 'pass')
|
262
|
-
.map(model => new PerformanceInsightFormatter(
|
275
|
+
.map(model => new PerformanceInsightFormatter(focus, model).getSuggestions().at(-1))
|
263
276
|
.filter(suggestion => !!suggestion)
|
264
277
|
.slice(0, 3);
|
265
278
|
suggestions.push(...top3FailingInsightSuggestions);
|
@@ -278,6 +291,7 @@ const MAX_FUNCTION_RESULT_BYTE_LENGTH = 16384 * 4;
|
|
278
291
|
*/
|
279
292
|
export class PerformanceAgent extends AiAgent<AgentFocus> {
|
280
293
|
#formatter: PerformanceTraceFormatter|null = null;
|
294
|
+
#lastEventForEnhancedQuery: Trace.Types.Events.Event|undefined;
|
281
295
|
#lastInsightForEnhancedQuery: Trace.Insights.Types.InsightModel|undefined;
|
282
296
|
#hasShownAnalyzeTraceContext = false;
|
283
297
|
|
@@ -298,6 +312,10 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
298
312
|
text: extraPreambleWhenNotExternal,
|
299
313
|
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
300
314
|
};
|
315
|
+
#freshTraceExtraPreambleFact: Host.AidaClient.RequestFact = {
|
316
|
+
text: extraPreambleWhenFreshTrace,
|
317
|
+
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
318
|
+
};
|
301
319
|
#networkDataDescriptionFact: Host.AidaClient.RequestFact = {
|
302
320
|
text: PerformanceTraceFormatter.networkDataFormatDescription,
|
303
321
|
metadata: {source: 'devtools', score: ScorePriority.CRITICAL}
|
@@ -371,10 +389,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
371
389
|
* 1. go to paulirish.com, record a trace
|
372
390
|
* 2. say "What performance issues exist with my page?"
|
373
391
|
* 3. then say "images"
|
374
|
-
*
|
375
|
-
* TODO(cjamcl): reduce the reliance on this by making sure all URL references
|
376
|
-
* (such as the insight formatters) add the "eventKey" as a suffix, just like all
|
377
|
-
* other events.
|
378
392
|
*/
|
379
393
|
#parseForKnownUrls(response: string): string {
|
380
394
|
const focus = this.context?.getItem();
|
@@ -403,8 +417,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
403
417
|
return match;
|
404
418
|
}
|
405
419
|
|
406
|
-
const request =
|
407
|
-
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);
|
408
421
|
if (!request) {
|
409
422
|
return match;
|
410
423
|
}
|
@@ -451,13 +464,21 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
451
464
|
const focus = context.getItem();
|
452
465
|
const selected: string[] = [];
|
453
466
|
|
454
|
-
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) {
|
455
476
|
// If this is a followup chat about the same call tree, don't include the call tree serialization again.
|
456
477
|
// We don't need to repeat it and we'd rather have more the context window space.
|
457
478
|
let contextString = '';
|
458
|
-
if (!this.#callTreeContextSet.has(focus.
|
459
|
-
contextString = focus.
|
460
|
-
this.#callTreeContextSet.add(focus.
|
479
|
+
if (!this.#callTreeContextSet.has(focus.callTree)) {
|
480
|
+
contextString = focus.callTree.serialize();
|
481
|
+
this.#callTreeContextSet.add(focus.callTree);
|
461
482
|
}
|
462
483
|
|
463
484
|
if (contextString) {
|
@@ -465,17 +486,17 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
465
486
|
}
|
466
487
|
}
|
467
488
|
|
468
|
-
if (focus.
|
489
|
+
if (focus.insight) {
|
469
490
|
// We only need to add Insight info to a prompt when the context changes. For example:
|
470
491
|
// User clicks Insight A. We need to send info on Insight A with the prompt.
|
471
492
|
// User asks follow up question. We do not need to resend Insight A with the prompt.
|
472
493
|
// User clicks Insight B. We now need to send info on Insight B with the prompt.
|
473
494
|
// User clicks Insight A. We should resend the Insight info with the prompt.
|
474
|
-
const includeInsightInfo = focus.
|
475
|
-
this.#lastInsightForEnhancedQuery = focus.
|
495
|
+
const includeInsightInfo = focus.insight !== this.#lastInsightForEnhancedQuery;
|
496
|
+
this.#lastInsightForEnhancedQuery = focus.insight;
|
476
497
|
|
477
498
|
if (includeInsightInfo) {
|
478
|
-
selected.push(`User selected the ${focus.
|
499
|
+
selected.push(`User selected the ${focus.insight.insightKey} insight.\n\n`);
|
479
500
|
}
|
480
501
|
}
|
481
502
|
|
@@ -587,11 +608,16 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
587
608
|
this.addFact(this.#notExternalExtraPreambleFact);
|
588
609
|
}
|
589
610
|
|
611
|
+
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(focus.parsedTrace);
|
612
|
+
if (isFresh) {
|
613
|
+
this.addFact(this.#freshTraceExtraPreambleFact);
|
614
|
+
}
|
615
|
+
|
590
616
|
this.addFact(this.#callFrameDataDescriptionFact);
|
591
617
|
this.addFact(this.#networkDataDescriptionFact);
|
592
618
|
|
593
619
|
if (!this.#traceFacts.length) {
|
594
|
-
this.#formatter = new PerformanceTraceFormatter(focus);
|
620
|
+
this.#formatter = new PerformanceTraceFormatter(focus, PerformanceInsightFormatter.create);
|
595
621
|
this.#createFactForTraceSummary();
|
596
622
|
this.#createFactForCriticalRequests();
|
597
623
|
this.#createFactForMainThreadBottomUpSummary();
|
@@ -623,7 +649,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
623
649
|
|
624
650
|
#declareFunctions(context: PerformanceTraceContext): void {
|
625
651
|
const focus = context.getItem();
|
626
|
-
const {parsedTrace, insightSet} = focus
|
652
|
+
const {parsedTrace, insightSet} = focus;
|
627
653
|
|
628
654
|
this.declareFunction<{insightName: string}, {details: string}>('getInsightDetails', {
|
629
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
|
}
|
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
|
|