chrome-devtools-frontend 1.0.1515446 → 1.0.1515988
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/docs/contributing/infrastructure.md +131 -82
- package/front_end/Tests.js +3 -29
- package/front_end/core/common/Progress.ts +73 -55
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +2 -0
- package/front_end/core/root/Runtime.ts +0 -1
- package/front_end/core/sdk/CSSMatchedStyles.ts +12 -10
- package/front_end/core/sdk/CSSModel.ts +1 -31
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +27 -7
- package/front_end/core/sdk/DebuggerModel.ts +1 -31
- package/front_end/core/sdk/EnhancedTracesParser.ts +81 -50
- package/front_end/core/sdk/NetworkManager.ts +1 -31
- package/front_end/core/sdk/NetworkRequest.ts +1 -31
- package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1003 -0
- package/front_end/core/sdk/RehydratingConnection.ts +13 -18
- package/front_end/core/sdk/RehydratingObject.ts +8 -31
- package/front_end/core/sdk/RemoteObject.ts +1 -31
- package/front_end/core/sdk/ResourceTreeModel.ts +1 -31
- package/front_end/core/sdk/RuntimeModel.ts +1 -31
- package/front_end/core/sdk/ServiceWorkerManager.ts +1 -31
- package/front_end/core/sdk/SourceMap.ts +1 -31
- package/front_end/core/sdk/TraceObject.ts +8 -3
- package/front_end/entrypoints/main/MainImpl.ts +0 -2
- package/front_end/entrypoints/main/main-meta.ts +2 -2
- package/front_end/generated/InspectorBackendCommands.js +4 -4
- package/front_end/generated/SupportedCSSProperties.js +12 -0
- package/front_end/generated/protocol.ts +10 -1
- package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -3
- package/front_end/models/ai_assistance/ConversationHandler.ts +4 -6
- package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +107 -72
- package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +2 -2
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +178 -85
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +308 -218
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +161 -97
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +78 -58
- package/front_end/models/ai_assistance/data_formatters/UnitFormatters.ts +10 -1
- package/front_end/models/ai_assistance/performance/AIContext.ts +19 -21
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +123 -55
- package/front_end/models/bindings/ContentProviderBasedProject.ts +6 -4
- package/front_end/models/breakpoints/BreakpointManager.ts +3 -3
- package/front_end/models/har/Writer.ts +11 -11
- package/front_end/models/javascript_metadata/NativeFunctions.js +7 -7
- package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +3 -3
- package/front_end/models/persistence/IsolatedFileSystem.ts +4 -4
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +7 -7
- package/front_end/models/persistence/PersistenceImpl.ts +8 -8
- package/front_end/models/persistence/PlatformFileSystem.ts +1 -1
- package/front_end/models/text_utils/TextUtils.ts +26 -0
- package/front_end/models/trace/ModelImpl.ts +2 -16
- package/front_end/models/trace/Processor.ts +14 -8
- package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +4 -4
- package/front_end/models/trace/handlers/FramesHandler.ts +2 -2
- package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +7 -10
- package/front_end/models/trace/handlers/MetaHandler.ts +11 -9
- package/front_end/models/trace/handlers/ScreenshotsHandler.ts +1 -1
- package/front_end/models/trace/handlers/ScriptsHandler.ts +5 -5
- package/front_end/models/trace/handlers/UserInteractionsHandler.ts +2 -14
- package/front_end/models/trace/handlers/UserTimingsHandler.ts +3 -4
- package/front_end/models/trace/insights/CLSCulprits.ts +1 -1
- package/front_end/models/trace/insights/DocumentLatency.ts +8 -7
- package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -1
- package/front_end/models/trace/insights/INPBreakdown.ts +1 -1
- package/front_end/models/trace/insights/ImageDelivery.ts +1 -1
- package/front_end/models/trace/insights/LCPBreakdown.ts +1 -1
- package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
- package/front_end/models/trace/insights/ModernHTTP.ts +1 -1
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -1
- package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
- package/front_end/models/trace/insights/types.ts +2 -0
- package/front_end/models/trace/types/Configuration.ts +12 -0
- package/front_end/models/trace/types/TraceEvents.ts +41 -64
- package/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -99
- package/front_end/panels/application/ServiceWorkersView.ts +0 -1
- package/front_end/panels/application/components/BackForwardCacheStrings.ts +8 -2
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -3
- package/front_end/panels/common/BadgeNotification.ts +10 -8
- package/front_end/panels/common/GdpSignUpDialog.ts +30 -14
- package/front_end/panels/common/gdpSignUpDialog.css +4 -0
- package/front_end/panels/console/ConsoleView.ts +23 -28
- package/front_end/panels/console/ConsoleViewport.ts +2 -2
- package/front_end/panels/console/consoleView.css +11 -1
- package/front_end/panels/coverage/CoverageView.ts +2 -2
- package/front_end/panels/elements/ElementsTreeOutline.ts +2 -2
- package/front_end/panels/elements/StyleEditorWidget.ts +8 -19
- package/front_end/panels/elements/StylePropertyTreeElement.ts +39 -25
- package/front_end/panels/elements/StylesSidebarPane.ts +2 -2
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +4 -3
- package/front_end/panels/layer_viewer/Layers3DView.ts +2 -2
- package/front_end/panels/layers/LayerTreeModel.ts +3 -3
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +4 -4
- package/front_end/panels/network/NetworkLogView.ts +1 -1
- package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
- package/front_end/panels/network/NetworkSearchScope.ts +6 -6
- package/front_end/panels/search/SearchView.ts +220 -159
- package/front_end/panels/settings/components/SyncSection.ts +64 -10
- package/front_end/panels/settings/components/syncSection.css +6 -0
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
- package/front_end/panels/sources/SourcesSearchScope.ts +4 -4
- package/front_end/panels/sources/TabbedEditorContainer.ts +5 -5
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +10 -5
- package/front_end/panels/timeline/TimelineFlameChartView.ts +18 -15
- package/front_end/panels/timeline/TimelinePanel.ts +41 -22
- package/front_end/panels/timeline/TracingLayerTree.ts +4 -5
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +37 -22
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +17 -7
- package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
- package/front_end/third_party/axe-core/README.chromium +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror/README.chromium +1 -0
- package/front_end/third_party/codemirror.next/README.chromium +1 -0
- package/front_end/third_party/csp_evaluator/README.chromium +1 -0
- package/front_end/third_party/diff/README.chromium +1 -0
- package/front_end/third_party/i18n/README.chromium +1 -0
- package/front_end/third_party/intl-messageformat/README.chromium +1 -0
- package/front_end/third_party/json5/README.chromium +1 -0
- package/front_end/third_party/legacy-javascript/README.chromium +1 -0
- package/front_end/third_party/lighthouse/README.chromium +1 -0
- package/front_end/third_party/lit/README.chromium +1 -0
- package/front_end/third_party/marked/README.chromium +1 -0
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/README.md +6 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +11 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +30 -8
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
- 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/cdp/NetworkManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +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.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -0
- 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/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +12 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +22 -8
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +11 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +30 -8
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +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.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +12 -2
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +13 -2
- package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +50 -8
- package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +0 -1
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +8 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +21 -5
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +12 -0
- package/front_end/third_party/puppeteer-replay/README.chromium +1 -0
- package/front_end/third_party/third-party-web/README.chromium +1 -0
- package/front_end/third_party/vscode.web-custom-data/README.chromium +1 -0
- package/front_end/third_party/wasmparser/README.chromium +1 -0
- package/front_end/third_party/web-vitals/README.chromium +1 -0
- package/front_end/ui/components/text_editor/config.ts +66 -16
- package/front_end/ui/components/tooltips/Tooltip.ts +17 -1
- package/front_end/ui/legacy/ContextMenu.ts +2 -2
- package/front_end/ui/legacy/GlassPane.ts +7 -3
- package/front_end/ui/legacy/ProgressIndicator.ts +33 -21
- package/front_end/ui/legacy/TabbedPane.ts +2 -2
- package/front_end/ui/legacy/Treeoutline.ts +10 -5
- package/front_end/ui/legacy/UIUtils.ts +42 -10
- package/front_end/ui/legacy/components/color_picker/Spectrum.ts +14 -14
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +6 -6
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -2
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +3 -29
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +14 -14
- package/front_end/ui/visual_logging/Debugging.ts +24 -12
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/inspector_overlay/highlight_common.ts +1 -27
- package/inspector_overlay/highlight_grid_common.ts +1 -27
- package/inspector_overlay/tool_highlight.ts +1 -27
- package/inspector_overlay/tool_persistent.ts +1 -27
- package/inspector_overlay/tool_source_order.ts +1 -27
- package/package.json +3 -3
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
import * as Common from '../../../core/common/common.js';
|
6
6
|
import * as Trace from '../../trace/trace.js';
|
7
|
-
import type {
|
7
|
+
import type {ConversationSuggestions} from '../agents/AiAgent.js';
|
8
8
|
|
9
9
|
import {
|
10
10
|
NetworkRequestFormatter,
|
@@ -103,7 +103,7 @@ export class PerformanceInsightFormatter {
|
|
103
103
|
return this.#description().length > 0;
|
104
104
|
}
|
105
105
|
|
106
|
-
getSuggestions():
|
106
|
+
getSuggestions(): ConversationSuggestions {
|
107
107
|
switch (this.#insight.insightKey) {
|
108
108
|
case 'CLSCulprits':
|
109
109
|
return [
|
@@ -206,6 +206,75 @@ export class PerformanceInsightFormatter {
|
|
206
206
|
return output;
|
207
207
|
}
|
208
208
|
|
209
|
+
/**
|
210
|
+
* Create an AI prompt string out of the CLS Culprits Insight model to use with Ask AI.
|
211
|
+
* @param insight The CLS Culprits Model to query.
|
212
|
+
* @returns a string formatted for sending to Ask AI.
|
213
|
+
*/
|
214
|
+
formatClsCulpritsInsight(insight: Trace.Insights.Models.CLSCulprits.CLSCulpritsInsightModel): string {
|
215
|
+
const {worstCluster, shifts} = insight;
|
216
|
+
if (!worstCluster) {
|
217
|
+
return '';
|
218
|
+
}
|
219
|
+
|
220
|
+
const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
|
221
|
+
|
222
|
+
const clusterTimes = {
|
223
|
+
start: worstCluster.ts - baseTime,
|
224
|
+
end: worstCluster.ts + worstCluster.dur - baseTime,
|
225
|
+
} as const;
|
226
|
+
|
227
|
+
const shiftsFormatted = worstCluster.events.map((layoutShift, index) => {
|
228
|
+
return TraceEventFormatter.layoutShift(layoutShift, index, this.#parsedTrace, shifts.get(layoutShift));
|
229
|
+
});
|
230
|
+
|
231
|
+
return `The worst layout shift cluster was the cluster that started at ${
|
232
|
+
this.#formatMicro(clusterTimes.start)} and ended at ${
|
233
|
+
this.#formatMicro(clusterTimes.end)}, with a duration of ${this.#formatMicro(worstCluster.dur)}.
|
234
|
+
The score for this cluster is ${worstCluster.clusterCumulativeScore.toFixed(4)}.
|
235
|
+
|
236
|
+
Layout shifts in this cluster:
|
237
|
+
${shiftsFormatted.join('\n')}`;
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
* Create an AI prompt string out of the Document Latency Insight model to use with Ask AI.
|
242
|
+
* @param insight The Document Latency Model to query.
|
243
|
+
* @returns a string formatted for sending to Ask AI.
|
244
|
+
*/
|
245
|
+
formatDocumentLatencyInsight(insight: Trace.Insights.Models.DocumentLatency.DocumentLatencyInsightModel): string {
|
246
|
+
if (!insight.data) {
|
247
|
+
return '';
|
248
|
+
}
|
249
|
+
const {checklist, documentRequest} = insight.data;
|
250
|
+
if (!documentRequest) {
|
251
|
+
return '';
|
252
|
+
}
|
253
|
+
const checklistBulletPoints: Array<{name: string, passed: boolean}> = [];
|
254
|
+
checklistBulletPoints.push({
|
255
|
+
name: 'The request was not redirected',
|
256
|
+
passed: checklist.noRedirects.value,
|
257
|
+
});
|
258
|
+
checklistBulletPoints.push({
|
259
|
+
name: 'Server responded quickly',
|
260
|
+
passed: checklist.serverResponseIsFast.value,
|
261
|
+
});
|
262
|
+
checklistBulletPoints.push({
|
263
|
+
name: 'Compression was applied',
|
264
|
+
passed: checklist.usesCompression.value,
|
265
|
+
});
|
266
|
+
|
267
|
+
return `${this.#lcpMetricSharedContext()}
|
268
|
+
|
269
|
+
${TraceEventFormatter.networkRequests([documentRequest], this.#parsedTrace, {
|
270
|
+
verbose: true,
|
271
|
+
customTitle: 'Document network request'
|
272
|
+
})}
|
273
|
+
|
274
|
+
The result of the checks for this insight are:
|
275
|
+
${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED' : 'FAILED'}`).join('\n')}`;
|
276
|
+
}
|
277
|
+
|
209
278
|
/**
|
210
279
|
* Create an AI prompt string out of the DOM Size model to use with Ask AI.
|
211
280
|
* Note: This function accesses the UIStrings within DomSize to help build the
|
@@ -262,6 +331,32 @@ export class PerformanceInsightFormatter {
|
|
262
331
|
return output;
|
263
332
|
}
|
264
333
|
|
334
|
+
/**
|
335
|
+
* Create an AI prompt string out of the Duplicated JavaScript Insight model to use with Ask AI.
|
336
|
+
* @param insight The Duplicated JavaScript Model to query.
|
337
|
+
* @returns a string formatted for sending to Ask AI.
|
338
|
+
*/
|
339
|
+
formatDuplicatedJavaScriptInsight(
|
340
|
+
insight: Trace.Insights.Models.DuplicatedJavaScript.DuplicatedJavaScriptInsightModel): string {
|
341
|
+
const totalWastedBytes = insight.wastedBytes;
|
342
|
+
const duplicatedScriptsByModule = insight.duplicationGroupedByNodeModules;
|
343
|
+
|
344
|
+
if (duplicatedScriptsByModule.size === 0) {
|
345
|
+
return 'There is no duplicated JavaScript in the page modules';
|
346
|
+
}
|
347
|
+
|
348
|
+
const filesFormatted =
|
349
|
+
Array.from(duplicatedScriptsByModule)
|
350
|
+
.map(
|
351
|
+
([module, duplication]) =>
|
352
|
+
`- Source: ${module} - Duplicated bytes: ${duplication.estimatedDuplicateBytes} bytes`)
|
353
|
+
.join('\n');
|
354
|
+
|
355
|
+
return `Total wasted bytes: ${totalWastedBytes} bytes.
|
356
|
+
|
357
|
+
Duplication grouped by Node modules: ${filesFormatted}`;
|
358
|
+
}
|
359
|
+
|
265
360
|
/**
|
266
361
|
* Create an AI prompt string out of the NetworkDependencyTree Insight model to use with Ask AI.
|
267
362
|
* Note: This function accesses the UIStrings within NetworkDependencyTree to help build the
|
@@ -344,6 +439,170 @@ export class PerformanceInsightFormatter {
|
|
344
439
|
return output;
|
345
440
|
}
|
346
441
|
|
442
|
+
/**
|
443
|
+
* Create an AI prompt string out of the INP Brekdown Insight model to use with Ask AI.
|
444
|
+
* @param insight The INP Breakdown Model to query.
|
445
|
+
* @returns a string formatted for sending to Ask AI.
|
446
|
+
*/
|
447
|
+
formatImageDeliveryInsight(insight: Trace.Insights.Models.ImageDelivery.ImageDeliveryInsightModel): string {
|
448
|
+
const optimizableImages = insight.optimizableImages;
|
449
|
+
if (optimizableImages.length === 0) {
|
450
|
+
return 'There are no unoptimized images on this page.';
|
451
|
+
}
|
452
|
+
|
453
|
+
const imageDetails = optimizableImages
|
454
|
+
.map(image => {
|
455
|
+
// List potential optimizations for the image
|
456
|
+
const optimizations =
|
457
|
+
image.optimizations
|
458
|
+
.map(optimization => {
|
459
|
+
const message =
|
460
|
+
Trace.Insights.Models.ImageDelivery.getOptimizationMessage(optimization);
|
461
|
+
const byteSavings = bytes(optimization.byteSavings);
|
462
|
+
return `${message} (Est ${byteSavings})`;
|
463
|
+
})
|
464
|
+
.join('\n');
|
465
|
+
|
466
|
+
return `### ${image.request.args.data.url}
|
467
|
+
- Potential savings: ${bytes(image.byteSavings)}
|
468
|
+
- Optimizations:\n${optimizations}`;
|
469
|
+
})
|
470
|
+
.join('\n\n');
|
471
|
+
|
472
|
+
return `Total potential savings: ${bytes(insight.wastedBytes)}
|
473
|
+
|
474
|
+
The following images could be optimized:\n\n${imageDetails}`;
|
475
|
+
}
|
476
|
+
|
477
|
+
/**
|
478
|
+
* Create an AI prompt string out of the INP Brekdown Insight model to use with Ask AI.
|
479
|
+
* @param insight The INP Breakdown Model to query.
|
480
|
+
* @returns a string formatted for sending to Ask AI.
|
481
|
+
*/
|
482
|
+
formatInpBreakdownInsight(insight: Trace.Insights.Models.INPBreakdown.INPBreakdownInsightModel): string {
|
483
|
+
const event = insight.longestInteractionEvent;
|
484
|
+
if (!event) {
|
485
|
+
return '';
|
486
|
+
}
|
487
|
+
|
488
|
+
const inpInfoForEvent =
|
489
|
+
`The longest interaction on the page was a \`${event.type}\` which had a total duration of \`${
|
490
|
+
this.#formatMicro(event.dur)}\`. The timings of each of the three phases were:
|
491
|
+
|
492
|
+
1. Input delay: ${this.#formatMicro(event.inputDelay)}
|
493
|
+
2. Processing duration: ${this.#formatMicro(event.mainThreadHandling)}
|
494
|
+
3. Presentation delay: ${this.#formatMicro(event.presentationDelay)}.`;
|
495
|
+
|
496
|
+
return inpInfoForEvent;
|
497
|
+
}
|
498
|
+
|
499
|
+
/**
|
500
|
+
* Create an AI prompt string out of the LCP Brekdown Insight model to use with Ask AI.
|
501
|
+
* @param insight The LCP Breakdown Model to query.
|
502
|
+
* @returns a string formatted for sending to Ask AI.
|
503
|
+
*/
|
504
|
+
formatLcpBreakdownInsight(insight: Trace.Insights.Models.LCPBreakdown.LCPBreakdownInsightModel): string {
|
505
|
+
const {subparts, lcpMs} = insight;
|
506
|
+
if (!lcpMs || !subparts) {
|
507
|
+
return '';
|
508
|
+
}
|
509
|
+
|
510
|
+
// Text based LCP has TTFB & Render delay
|
511
|
+
// Image based has TTFB, Load delay, Load time and Render delay
|
512
|
+
// Note that we expect every trace + LCP to have TTFB + Render delay, but
|
513
|
+
// very old traces are missing the data, so we have to code defensively
|
514
|
+
// in case the subparts are not present.
|
515
|
+
const phaseBulletPoints: Array<{name: string, value: string, percentage: string}> = [];
|
516
|
+
|
517
|
+
Object.values(subparts).forEach((subpart: Trace.Insights.Models.LCPBreakdown.Subpart) => {
|
518
|
+
const phaseMilli = Trace.Helpers.Timing.microToMilli(subpart.range);
|
519
|
+
const percentage = (phaseMilli / lcpMs * 100).toFixed(1);
|
520
|
+
phaseBulletPoints.push({name: subpart.label, value: this.#formatMilli(phaseMilli), percentage});
|
521
|
+
});
|
522
|
+
|
523
|
+
return `${this.#lcpMetricSharedContext()}
|
524
|
+
|
525
|
+
We can break this time down into the ${phaseBulletPoints.length} phases that combine to make the LCP time:
|
526
|
+
|
527
|
+
${
|
528
|
+
phaseBulletPoints.map(phase => `- ${phase.name}: ${phase.value} (${phase.percentage}% of total LCP time)`)
|
529
|
+
.join('\n')}`;
|
530
|
+
}
|
531
|
+
|
532
|
+
/**
|
533
|
+
* Create an AI prompt string out of the LCP Brekdown Insight model to use with Ask AI.
|
534
|
+
* @param insight The LCP Breakdown Model to query.
|
535
|
+
* @returns a string formatted for sending to Ask AI.
|
536
|
+
*/
|
537
|
+
formatLcpDiscoveryInsight(insight: Trace.Insights.Models.LCPDiscovery.LCPDiscoveryInsightModel): string {
|
538
|
+
const {checklist, lcpEvent, lcpRequest, earliestDiscoveryTimeTs} = insight;
|
539
|
+
if (!checklist || !lcpEvent || !lcpRequest || !earliestDiscoveryTimeTs) {
|
540
|
+
return '';
|
541
|
+
}
|
542
|
+
|
543
|
+
const checklistBulletPoints: Array<{name: string, passed: boolean}> = [];
|
544
|
+
checklistBulletPoints.push({
|
545
|
+
name: checklist.priorityHinted.label,
|
546
|
+
passed: checklist.priorityHinted.value,
|
547
|
+
});
|
548
|
+
checklistBulletPoints.push({
|
549
|
+
name: checklist.eagerlyLoaded.label,
|
550
|
+
passed: checklist.eagerlyLoaded.value,
|
551
|
+
});
|
552
|
+
checklistBulletPoints.push({
|
553
|
+
name: checklist.requestDiscoverable.label,
|
554
|
+
passed: checklist.requestDiscoverable.value,
|
555
|
+
});
|
556
|
+
|
557
|
+
return `${this.#lcpMetricSharedContext()}
|
558
|
+
|
559
|
+
The result of the checks for this insight are:
|
560
|
+
${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED' : 'FAILED'}`).join('\n')}`;
|
561
|
+
}
|
562
|
+
|
563
|
+
/**
|
564
|
+
* Create an AI prompt string out of the Legacy JavaScript Insight model to use with Ask AI.
|
565
|
+
* @param insight The Legacy JavaScript Model to query.
|
566
|
+
* @returns a string formatted for sending to Ask AI.
|
567
|
+
*/
|
568
|
+
formatLegacyJavaScriptInsight(insight: Trace.Insights.Models.LegacyJavaScript.LegacyJavaScriptInsightModel): string {
|
569
|
+
const legacyJavaScriptResults = insight.legacyJavaScriptResults;
|
570
|
+
|
571
|
+
if (legacyJavaScriptResults.size === 0) {
|
572
|
+
return 'There is no significant amount of legacy JavaScript on the page.';
|
573
|
+
}
|
574
|
+
|
575
|
+
const filesFormatted =
|
576
|
+
Array.from(legacyJavaScriptResults)
|
577
|
+
.map(([script, result]) => `\n- Script: ${script.url} - Wasted bytes: ${result.estimatedByteSavings} bytes
|
578
|
+
Matches:
|
579
|
+
${result.matches.map(match => `Line: ${match.line}, Column: ${match.column}, Name: ${match.name}`).join('\n')}`)
|
580
|
+
.join('\n');
|
581
|
+
|
582
|
+
return `Total legacy JavaScript: ${legacyJavaScriptResults.size} files.
|
583
|
+
|
584
|
+
Legacy JavaScript by file:
|
585
|
+
${filesFormatted}`;
|
586
|
+
}
|
587
|
+
|
588
|
+
/**
|
589
|
+
* Create an AI prompt string out of the Modern HTTP Insight model to use with Ask AI.
|
590
|
+
* @param insight The Modern HTTP Model to query.
|
591
|
+
* @returns a string formatted for sending to Ask AI.
|
592
|
+
*/
|
593
|
+
formatModernHttpInsight(insight: Trace.Insights.Models.ModernHTTP.ModernHTTPInsightModel): string {
|
594
|
+
const requestSummary = (insight.http1Requests.length === 1) ?
|
595
|
+
TraceEventFormatter.networkRequests(insight.http1Requests, this.#parsedTrace, {verbose: true}) :
|
596
|
+
TraceEventFormatter.networkRequests(insight.http1Requests, this.#parsedTrace);
|
597
|
+
|
598
|
+
if (requestSummary.length === 0) {
|
599
|
+
return 'There are no requests that were served over a legacy HTTP protocol.';
|
600
|
+
}
|
601
|
+
|
602
|
+
return `Here is a list of the network requests that were served over a legacy HTTP protocol:
|
603
|
+
${requestSummary}`;
|
604
|
+
}
|
605
|
+
|
347
606
|
/**
|
348
607
|
* Create an AI prompt string out of the NetworkDependencyTree Insight model to use with Ask AI.
|
349
608
|
* Note: This function accesses the UIStrings within NetworkDependencyTree to help build the
|
@@ -425,6 +684,23 @@ export class PerformanceInsightFormatter {
|
|
425
684
|
return output;
|
426
685
|
}
|
427
686
|
|
687
|
+
/**
|
688
|
+
* Create an AI prompt string out of the Render Blocking Insight model to use with Ask AI.
|
689
|
+
* @param insight The Render Blocking Model to query.
|
690
|
+
* @returns a string formatted for sending to Ask AI.
|
691
|
+
*/
|
692
|
+
formatRenderBlockingInsight(insight: Trace.Insights.Models.RenderBlocking.RenderBlockingInsightModel): string {
|
693
|
+
const requestSummary = TraceEventFormatter.networkRequests(insight.renderBlockingRequests, this.#parsedTrace);
|
694
|
+
|
695
|
+
if (requestSummary.length === 0) {
|
696
|
+
return 'There are no network requests that are render blocking.';
|
697
|
+
}
|
698
|
+
|
699
|
+
return `Here is a list of the network requests that were render blocking on this page and their duration:
|
700
|
+
|
701
|
+
${requestSummary}`;
|
702
|
+
}
|
703
|
+
|
428
704
|
/**
|
429
705
|
* Create an AI prompt string out of the Slow CSS Selector Insight model to use with Ask AI.
|
430
706
|
* Note: This function accesses the UIStrings within SlowCSSSelector to help build the
|
@@ -563,250 +839,64 @@ ${this.#links()}`;
|
|
563
839
|
}
|
564
840
|
|
565
841
|
#details(): string {
|
566
|
-
if (Trace.Insights.Models.
|
567
|
-
|
568
|
-
if (optimizableImages.length === 0) {
|
569
|
-
return 'There are no unoptimized images on this page.';
|
570
|
-
}
|
571
|
-
|
572
|
-
const imageDetails = optimizableImages
|
573
|
-
.map(image => {
|
574
|
-
// List potential optimizations for the image
|
575
|
-
const optimizations =
|
576
|
-
image.optimizations
|
577
|
-
.map(optimization => {
|
578
|
-
const message =
|
579
|
-
Trace.Insights.Models.ImageDelivery.getOptimizationMessage(optimization);
|
580
|
-
const byteSavings = bytes(optimization.byteSavings);
|
581
|
-
return `${message} (Est ${byteSavings})`;
|
582
|
-
})
|
583
|
-
.join('\n');
|
584
|
-
|
585
|
-
return `### ${image.request.args.data.url}
|
586
|
-
- Potential savings: ${bytes(image.byteSavings)}
|
587
|
-
- Optimizations:\n${optimizations}`;
|
588
|
-
})
|
589
|
-
.join('\n\n');
|
590
|
-
|
591
|
-
return `Total potential savings: ${bytes(this.#insight.wastedBytes)}
|
592
|
-
|
593
|
-
The following images could be optimized:\n\n${imageDetails}`;
|
842
|
+
if (Trace.Insights.Models.Cache.isCacheInsight(this.#insight)) {
|
843
|
+
return this.formatCacheInsight(this.#insight);
|
594
844
|
}
|
595
845
|
|
596
|
-
if (Trace.Insights.Models.
|
597
|
-
|
598
|
-
if (!lcpMs || !subparts) {
|
599
|
-
return '';
|
600
|
-
}
|
601
|
-
|
602
|
-
// Text based LCP has TTFB & Render delay
|
603
|
-
// Image based has TTFB, Load delay, Load time and Render delay
|
604
|
-
// Note that we expect every trace + LCP to have TTFB + Render delay, but
|
605
|
-
// very old traces are missing the data, so we have to code defensively
|
606
|
-
// in case the subparts are not present.
|
607
|
-
const phaseBulletPoints: Array<{name: string, value: string, percentage: string}> = [];
|
608
|
-
|
609
|
-
Object.values(subparts).forEach((subpart: Trace.Insights.Models.LCPBreakdown.Subpart) => {
|
610
|
-
const phaseMilli = Trace.Helpers.Timing.microToMilli(subpart.range);
|
611
|
-
const percentage = (phaseMilli / lcpMs * 100).toFixed(1);
|
612
|
-
phaseBulletPoints.push({name: subpart.label, value: this.#formatMilli(phaseMilli), percentage});
|
613
|
-
});
|
614
|
-
|
615
|
-
return `${this.#lcpMetricSharedContext()}
|
616
|
-
|
617
|
-
We can break this time down into the ${phaseBulletPoints.length} phases that combine to make the LCP time:
|
618
|
-
|
619
|
-
${
|
620
|
-
phaseBulletPoints.map(phase => `- ${phase.name}: ${phase.value} (${phase.percentage}% of total LCP time)`)
|
621
|
-
.join('\n')}`;
|
846
|
+
if (Trace.Insights.Models.CLSCulprits.isCLSCulpritsInsight(this.#insight)) {
|
847
|
+
return this.formatClsCulpritsInsight(this.#insight);
|
622
848
|
}
|
623
849
|
|
624
|
-
if (Trace.Insights.Models.
|
625
|
-
|
626
|
-
if (!checklist || !lcpEvent || !lcpRequest || !earliestDiscoveryTimeTs) {
|
627
|
-
return '';
|
628
|
-
}
|
629
|
-
|
630
|
-
const checklistBulletPoints: Array<{name: string, passed: boolean}> = [];
|
631
|
-
checklistBulletPoints.push({
|
632
|
-
name: checklist.priorityHinted.label,
|
633
|
-
passed: checklist.priorityHinted.value,
|
634
|
-
});
|
635
|
-
checklistBulletPoints.push({
|
636
|
-
name: checklist.eagerlyLoaded.label,
|
637
|
-
passed: checklist.eagerlyLoaded.value,
|
638
|
-
});
|
639
|
-
checklistBulletPoints.push({
|
640
|
-
name: checklist.requestDiscoverable.label,
|
641
|
-
passed: checklist.requestDiscoverable.value,
|
642
|
-
});
|
643
|
-
|
644
|
-
return `${this.#lcpMetricSharedContext()}
|
645
|
-
|
646
|
-
The result of the checks for this insight are:
|
647
|
-
${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED' : 'FAILED'}`).join('\n')}`;
|
850
|
+
if (Trace.Insights.Models.DocumentLatency.isDocumentLatencyInsight(this.#insight)) {
|
851
|
+
return this.formatDocumentLatencyInsight(this.#insight);
|
648
852
|
}
|
649
853
|
|
650
|
-
if (Trace.Insights.Models.
|
651
|
-
|
652
|
-
TraceEventFormatter.networkRequests(this.#insight.renderBlockingRequests, this.#parsedTrace);
|
653
|
-
|
654
|
-
if (requestSummary.length === 0) {
|
655
|
-
return 'There are no network requests that are render blocking.';
|
656
|
-
}
|
657
|
-
|
658
|
-
return `Here is a list of the network requests that were render blocking on this page and their duration:
|
659
|
-
|
660
|
-
${requestSummary}`;
|
854
|
+
if (Trace.Insights.Models.DOMSize.isDomSizeInsight(this.#insight)) {
|
855
|
+
return this.formatDomSizeInsight(this.#insight);
|
661
856
|
}
|
662
857
|
|
663
|
-
if (Trace.Insights.Models.
|
664
|
-
|
665
|
-
return '';
|
666
|
-
}
|
667
|
-
const {checklist, documentRequest} = this.#insight.data;
|
668
|
-
if (!documentRequest) {
|
669
|
-
return '';
|
670
|
-
}
|
671
|
-
const checklistBulletPoints: Array<{name: string, passed: boolean}> = [];
|
672
|
-
checklistBulletPoints.push({
|
673
|
-
name: 'The request was not redirected',
|
674
|
-
passed: checklist.noRedirects.value,
|
675
|
-
});
|
676
|
-
checklistBulletPoints.push({
|
677
|
-
name: 'Server responded quickly',
|
678
|
-
passed: checklist.serverResponseIsFast.value,
|
679
|
-
});
|
680
|
-
checklistBulletPoints.push({
|
681
|
-
name: 'Compression was applied',
|
682
|
-
passed: checklist.usesCompression.value,
|
683
|
-
});
|
684
|
-
|
685
|
-
return `${this.#lcpMetricSharedContext()}
|
686
|
-
|
687
|
-
${TraceEventFormatter.networkRequests([documentRequest], this.#parsedTrace, {
|
688
|
-
verbose: true,
|
689
|
-
customTitle: 'Document network request'
|
690
|
-
})}
|
691
|
-
|
692
|
-
The result of the checks for this insight are:
|
693
|
-
${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED' : 'FAILED'}`).join('\n')}`;
|
858
|
+
if (Trace.Insights.Models.DuplicatedJavaScript.isDuplicatedJavaScriptInsight(this.#insight)) {
|
859
|
+
return this.formatDuplicatedJavaScriptInsight(this.#insight);
|
694
860
|
}
|
695
861
|
|
696
|
-
if (Trace.Insights.Models.
|
697
|
-
|
698
|
-
if (!event) {
|
699
|
-
return '';
|
700
|
-
}
|
701
|
-
|
702
|
-
const inpInfoForEvent =
|
703
|
-
`The longest interaction on the page was a \`${event.type}\` which had a total duration of \`${
|
704
|
-
this.#formatMicro(event.dur)}\`. The timings of each of the three phases were:
|
705
|
-
|
706
|
-
1. Input delay: ${this.#formatMicro(event.inputDelay)}
|
707
|
-
2. Processing duration: ${this.#formatMicro(event.mainThreadHandling)}
|
708
|
-
3. Presentation delay: ${this.#formatMicro(event.presentationDelay)}.`;
|
709
|
-
|
710
|
-
return inpInfoForEvent;
|
862
|
+
if (Trace.Insights.Models.FontDisplay.isFontDisplayInsight(this.#insight)) {
|
863
|
+
return this.formatFontDisplayInsight(this.#insight);
|
711
864
|
}
|
712
865
|
|
713
|
-
if (Trace.Insights.Models.
|
714
|
-
|
715
|
-
if (!worstCluster) {
|
716
|
-
return '';
|
717
|
-
}
|
718
|
-
|
719
|
-
const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
|
720
|
-
|
721
|
-
const clusterTimes = {
|
722
|
-
start: worstCluster.ts - baseTime,
|
723
|
-
end: worstCluster.ts + worstCluster.dur - baseTime,
|
724
|
-
} as const;
|
725
|
-
|
726
|
-
const shiftsFormatted = worstCluster.events.map((layoutShift, index) => {
|
727
|
-
return TraceEventFormatter.layoutShift(layoutShift, index, this.#parsedTrace, shifts.get(layoutShift));
|
728
|
-
});
|
729
|
-
|
730
|
-
return `The worst layout shift cluster was the cluster that started at ${
|
731
|
-
this.#formatMicro(clusterTimes.start)} and ended at ${
|
732
|
-
this.#formatMicro(clusterTimes.end)}, with a duration of ${this.#formatMicro(worstCluster.dur)}.
|
733
|
-
The score for this cluster is ${worstCluster.clusterCumulativeScore.toFixed(4)}.
|
734
|
-
|
735
|
-
Layout shifts in this cluster:
|
736
|
-
${shiftsFormatted.join('\n')}`;
|
866
|
+
if (Trace.Insights.Models.ForcedReflow.isForcedReflowInsight(this.#insight)) {
|
867
|
+
return this.formatForcedReflowInsight(this.#insight);
|
737
868
|
}
|
738
869
|
|
739
|
-
if (Trace.Insights.Models.
|
740
|
-
|
741
|
-
TraceEventFormatter.networkRequests(this.#insight.http1Requests, this.#parsedTrace, {verbose: true}) :
|
742
|
-
TraceEventFormatter.networkRequests(this.#insight.http1Requests, this.#parsedTrace);
|
743
|
-
|
744
|
-
if (requestSummary.length === 0) {
|
745
|
-
return 'There are no requests that were served over a legacy HTTP protocol.';
|
746
|
-
}
|
747
|
-
|
748
|
-
return `Here is a list of the network requests that were served over a legacy HTTP protocol:
|
749
|
-
${requestSummary}`;
|
870
|
+
if (Trace.Insights.Models.ImageDelivery.isImageDeliveryInsight(this.#insight)) {
|
871
|
+
return this.formatImageDeliveryInsight(this.#insight);
|
750
872
|
}
|
751
873
|
|
752
|
-
if (Trace.Insights.Models.
|
753
|
-
|
754
|
-
const duplicatedScriptsByModule = this.#insight.duplicationGroupedByNodeModules;
|
755
|
-
|
756
|
-
if (duplicatedScriptsByModule.size === 0) {
|
757
|
-
return 'There is no duplicated JavaScript in the page modules';
|
758
|
-
}
|
759
|
-
|
760
|
-
const filesFormatted =
|
761
|
-
Array.from(duplicatedScriptsByModule)
|
762
|
-
.map(
|
763
|
-
([module, duplication]) =>
|
764
|
-
`- Source: ${module} - Duplicated bytes: ${duplication.estimatedDuplicateBytes} bytes`)
|
765
|
-
.join('\n');
|
766
|
-
|
767
|
-
return `Total wasted bytes: ${totalWastedBytes} bytes.
|
768
|
-
|
769
|
-
Duplication grouped by Node modules: ${filesFormatted}`;
|
874
|
+
if (Trace.Insights.Models.INPBreakdown.isINPBreakdownInsight(this.#insight)) {
|
875
|
+
return this.formatInpBreakdownInsight(this.#insight);
|
770
876
|
}
|
771
877
|
|
772
|
-
if (Trace.Insights.Models.
|
773
|
-
|
774
|
-
|
775
|
-
if (legacyJavaScriptResults.size === 0) {
|
776
|
-
return 'There is no significant amount of legacy JavaScript on the page.';
|
777
|
-
}
|
778
|
-
|
779
|
-
const filesFormatted =
|
780
|
-
Array.from(legacyJavaScriptResults)
|
781
|
-
.map(([script, result]) => `\n- Script: ${script.url} - Wasted bytes: ${result.estimatedByteSavings} bytes
|
782
|
-
Matches:
|
783
|
-
${result.matches.map(match => `Line: ${match.line}, Column: ${match.column}, Name: ${match.name}`).join('\n')}`)
|
784
|
-
.join('\n');
|
785
|
-
|
786
|
-
return `Total legacy JavaScript: ${legacyJavaScriptResults.size} files.
|
787
|
-
|
788
|
-
Legacy JavaScript by file:
|
789
|
-
${filesFormatted}`;
|
878
|
+
if (Trace.Insights.Models.LCPBreakdown.isLCPBreakdownInsight(this.#insight)) {
|
879
|
+
return this.formatLcpBreakdownInsight(this.#insight);
|
790
880
|
}
|
791
881
|
|
792
|
-
if (Trace.Insights.Models.
|
793
|
-
return this.
|
882
|
+
if (Trace.Insights.Models.LCPDiscovery.isLCPDiscoveryInsight(this.#insight)) {
|
883
|
+
return this.formatLcpDiscoveryInsight(this.#insight);
|
794
884
|
}
|
795
885
|
|
796
|
-
if (Trace.Insights.Models.
|
797
|
-
return this.
|
886
|
+
if (Trace.Insights.Models.LegacyJavaScript.isLegacyJavaScript(this.#insight)) {
|
887
|
+
return this.formatLegacyJavaScriptInsight(this.#insight);
|
798
888
|
}
|
799
889
|
|
800
|
-
if (Trace.Insights.Models.
|
801
|
-
return this.
|
890
|
+
if (Trace.Insights.Models.ModernHTTP.isModernHTTPInsight(this.#insight)) {
|
891
|
+
return this.formatModernHttpInsight(this.#insight);
|
802
892
|
}
|
803
893
|
|
804
|
-
if (Trace.Insights.Models.
|
805
|
-
return this.
|
894
|
+
if (Trace.Insights.Models.NetworkDependencyTree.isNetworkDependencyTreeInsight(this.#insight)) {
|
895
|
+
return this.formatNetworkDependencyTreeInsight(this.#insight);
|
806
896
|
}
|
807
897
|
|
808
|
-
if (Trace.Insights.Models.
|
809
|
-
return this.
|
898
|
+
if (Trace.Insights.Models.RenderBlocking.isRenderBlockingInsight(this.#insight)) {
|
899
|
+
return this.formatRenderBlockingInsight(this.#insight);
|
810
900
|
}
|
811
901
|
|
812
902
|
if (Trace.Insights.Models.SlowCSSSelector.isSlowCSSSelectorInsight(this.#insight)) {
|