chrome-devtools-frontend 1.0.1537268 → 1.0.1537860
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/.env.template +9 -0
- package/docs/get_the_code.md +27 -0
- package/front_end/core/common/SettingRegistration.ts +10 -7
- package/front_end/core/common/Settings.ts +3 -0
- package/front_end/core/sdk/sdk-meta.ts +8 -2
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +4 -3
- package/front_end/generated/SupportedCSSProperties.js +1 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +23 -7
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +110 -5
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +50 -45
- package/front_end/models/cpu_profile/ProfileTreeModel.ts +7 -7
- package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +1 -1
- package/front_end/panels/application/StorageView.ts +3 -2
- package/front_end/panels/application/components/BackForwardCacheView.ts +34 -51
- package/front_end/panels/application/components/OriginTrialTreeView.ts +83 -80
- package/front_end/panels/application/components/backForwardCacheView.css +4 -0
- package/front_end/panels/application/components/badge.css +8 -0
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingString.ts +27 -0
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +11 -9
- package/front_end/panels/coverage/CoverageView.ts +1 -2
- package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +1 -1
- package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
- package/front_end/panels/elements/ElementStatePaneWidget.ts +1 -1
- package/front_end/panels/elements/EventListenersWidget.ts +1 -2
- package/front_end/panels/elements/PropertiesWidget.ts +1 -1
- package/front_end/panels/network/NetworkConfigView.ts +2 -1
- package/front_end/panels/network/NetworkPanel.ts +5 -4
- package/front_end/panels/network/RequestCookiesView.ts +2 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -2
- package/front_end/panels/sensors/SensorsView.ts +4 -3
- package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +8 -6
- package/front_end/panels/settings/KeybindsSettingsTab.ts +3 -2
- package/front_end/panels/settings/SettingsScreen.ts +2 -1
- package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +2 -1
- package/front_end/panels/sources/SourcesPanel.ts +2 -1
- package/front_end/panels/sources/sources-meta.ts +8 -1
- package/front_end/panels/timeline/TimelinePanel.ts +4 -3
- package/front_end/panels/timeline/TimelineUIUtils.ts +4 -20
- package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -0
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +2 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/adorners/Adorner.ts +2 -1
- package/front_end/ui/components/buttons/Button.docs.ts +195 -0
- package/front_end/ui/components/settings/SettingCheckbox.ts +49 -14
- package/front_end/ui/components/settings/settingCheckbox.css +6 -1
- package/front_end/ui/components/spinners/Spinners.docs.ts +13 -0
- package/front_end/ui/components/tooltips/Tooltip.docs.ts +76 -0
- package/front_end/ui/legacy/FilterBar.ts +1 -2
- package/front_end/ui/legacy/RadioButton.docs.ts +41 -0
- package/front_end/ui/legacy/SelectMenu.docs.ts +98 -0
- package/front_end/ui/legacy/Toolbar.ts +4 -6
- package/front_end/ui/legacy/UIUtils.ts +114 -1
- package/front_end/ui/legacy/Widget.ts +62 -34
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +125 -0
- package/front_end/ui/legacy/components/settings_ui/settings_ui.ts +8 -0
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/package.json +1 -1
- package/front_end/models/trace/lantern/testing/MetricTestUtils.ts +0 -62
- package/front_end/models/trace/lantern/testing/testing.ts +0 -5
- package/front_end/ui/components/docs/button/basic.html +0 -44
- package/front_end/ui/components/docs/button/basic.ts +0 -175
- package/front_end/ui/components/docs/radio_button/basic.html +0 -23
- package/front_end/ui/components/docs/radio_button/basic.ts +0 -50
- package/front_end/ui/components/docs/select_menu/basic.html +0 -19
- package/front_end/ui/components/docs/select_menu/basic.ts +0 -95
- package/front_end/ui/components/docs/select_menu/wide-option.html +0 -38
- package/front_end/ui/components/docs/select_menu/wide-option.ts +0 -43
- package/front_end/ui/components/docs/spinners/basic.html +0 -17
- package/front_end/ui/components/docs/spinners/basic.ts +0 -22
- package/front_end/ui/components/docs/tooltip/basic.html +0 -20
- package/front_end/ui/components/docs/tooltip/basic.ts +0 -82
- package/front_end/ui/legacy/SettingsUI.ts +0 -240
package/.env.template
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# This files is to be used when calling node script
|
|
2
|
+
# Use --env-file-if-exists to make it optional
|
|
3
|
+
DEVTOOLS_BROWSER=
|
|
4
|
+
DEVTOOLS_UNSTABLE_FEATURES=
|
|
5
|
+
DEVTOOLS_ENABLE_FEATURES=
|
|
6
|
+
DEVTOOLS_AUTO_OPEN_DEVTOOLS=
|
|
7
|
+
DEVTOOLS_REMOTE_DEBUGGING_PORT=
|
|
8
|
+
DEVTOOLS_TARGET=
|
|
9
|
+
DEVTOOLS_USER_DATA_DIR=
|
package/docs/get_the_code.md
CHANGED
|
@@ -100,6 +100,33 @@ sudo sysctl -p
|
|
|
100
100
|
You may also need to pay attention to the values of `max_queued_events` and `max_user_instances`
|
|
101
101
|
if you encounter any errors.
|
|
102
102
|
|
|
103
|
+
### Using a `.env` file for default script options
|
|
104
|
+
|
|
105
|
+
Many scripts, like `npm run build` and `npm start`, accept command-line flags to configure their behavior (e.g., `-t <target>`, `--browser=<name>`).
|
|
106
|
+
|
|
107
|
+
To avoid typing these flags every time, you can set your preferred defaults in a .env file at the root of the devtools-frontend directory.
|
|
108
|
+
|
|
109
|
+
The `.env.template` file lists all supported variables. Copy it to `.env` to get started.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cp .env.template .env
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
As mentioned earlier, you might create a fast build target. Instead of always typing `npm run build -- -t fast-build`, to remove the flag repetition you simple run `npm run build` you can set the following variable in your `.env` file:
|
|
116
|
+
|
|
117
|
+
```shell
|
|
118
|
+
DEVTOOLS_TARGET=fast-build
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Another example - by default running `npm start` auto-opens DevTools for new Tabs.
|
|
122
|
+
You may want to disable this so fewer pop-up happen while debugging, usually done via `--no-open` flag. Or with `.env` set the following value:
|
|
123
|
+
|
|
124
|
+
```shell
|
|
125
|
+
DEVTOOLS_AUTO_OPEN_DEVTOOLS=false
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
To use `.env` file from other script, refer to the helper in `scripts/env-utils.mjs`. That should provide the necessary helper to work with the config, and make maintenance simpler.
|
|
129
|
+
|
|
103
130
|
### Update to latest
|
|
104
131
|
|
|
105
132
|
To update to latest tip of tree version:
|
|
@@ -299,21 +299,24 @@ export interface SettingRegistration {
|
|
|
299
299
|
* jump to the experiment. If a setting is not disabled, the experiment entry will be ignored.
|
|
300
300
|
*/
|
|
301
301
|
deprecationNotice?: {disabled: boolean, warning: () => Platform.UIString.LocalizedString, experiment?: string};
|
|
302
|
-
|
|
303
302
|
/**
|
|
304
|
-
*
|
|
305
|
-
* in the Settings panel with a link to learn more, and the `tooltip` will be presented to the user when hovering
|
|
306
|
-
* the `(?)` icon.
|
|
303
|
+
* See {@link LearnMore} for more info.
|
|
307
304
|
*/
|
|
308
305
|
learnMore?: LearnMore;
|
|
309
306
|
}
|
|
310
307
|
|
|
311
308
|
/**
|
|
312
|
-
*
|
|
313
|
-
*
|
|
309
|
+
* Optional information to learn more about the setting.
|
|
310
|
+
*
|
|
311
|
+
* If tooltip is provided creates a (i) icon with rich tooltip with said tooltip
|
|
312
|
+
*
|
|
313
|
+
* If url is provided creates a (?) icon with a link to said url
|
|
314
|
+
*
|
|
315
|
+
* If both tooltip is provided creates a (i) icon with rich tooltip
|
|
316
|
+
* and a link inside the rich tool tip with text `Learn more`
|
|
314
317
|
*/
|
|
315
318
|
export interface LearnMore {
|
|
316
|
-
tooltip
|
|
319
|
+
tooltip?: () => Platform.UIString.LocalizedString;
|
|
317
320
|
url?: Platform.DevToolsPath.UrlString;
|
|
318
321
|
}
|
|
319
322
|
|
|
@@ -353,8 +353,11 @@ const UIStrings = {
|
|
|
353
353
|
/**
|
|
354
354
|
* @description Label of a checkbox in the DevTools settings UI.
|
|
355
355
|
*/
|
|
356
|
-
enableRemoteFileLoading:
|
|
357
|
-
|
|
356
|
+
enableRemoteFileLoading: 'Allow loading remote file path resources in DevTools',
|
|
357
|
+
/**
|
|
358
|
+
* @description Tooltip text for a setting that controls whether external resource can be loaded in DevTools.
|
|
359
|
+
*/
|
|
360
|
+
remoteFileLoadingInfo: 'Example resource are source maps. Disabled by default for security reasons.',
|
|
358
361
|
/**
|
|
359
362
|
* @description Tooltip text for a setting that controls the network cache. Disabling the network cache can simulate the network connections of users that are visiting a page for the first time.
|
|
360
363
|
*/
|
|
@@ -1160,4 +1163,7 @@ Common.Settings.registerSettingExtension({
|
|
|
1160
1163
|
settingName: 'network.enable-remote-file-loading',
|
|
1161
1164
|
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
1162
1165
|
defaultValue: false,
|
|
1166
|
+
learnMore: {
|
|
1167
|
+
tooltip: i18nLazyString(UIStrings.remoteFileLoadingInfo),
|
|
1168
|
+
}
|
|
1163
1169
|
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import * as Common from '../../core/common/common.js';
|
|
8
8
|
import * as Host from '../../core/host/host.js';
|
|
9
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
10
|
+
import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
|
|
10
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
11
12
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
12
13
|
|
|
@@ -278,15 +279,15 @@ export class RenderingOptionsView extends UI.Widget.VBox {
|
|
|
278
279
|
|
|
279
280
|
#appendCheckbox(
|
|
280
281
|
label: Common.UIString.LocalizedString, subtitle: Common.UIString.LocalizedString,
|
|
281
|
-
setting: Common.Settings.Setting<boolean>, metric?: UI.
|
|
282
|
+
setting: Common.Settings.Setting<boolean>, metric?: UI.UIUtils.UserMetricOptions): UI.UIUtils.CheckboxLabel {
|
|
282
283
|
const checkbox = UI.UIUtils.CheckboxLabel.create(label, false, subtitle, setting.name);
|
|
283
|
-
UI.
|
|
284
|
+
UI.UIUtils.bindCheckbox(checkbox, setting, metric);
|
|
284
285
|
this.contentElement.appendChild(checkbox);
|
|
285
286
|
return checkbox;
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
#appendSelect(label: string, setting: Common.Settings.Setting<unknown>): void {
|
|
289
|
-
const control =
|
|
290
|
+
const control = SettingsUI.SettingsUI.createControlForSetting(setting, label);
|
|
290
291
|
if (control) {
|
|
291
292
|
this.contentElement.appendChild(control);
|
|
292
293
|
}
|
|
@@ -627,19 +627,24 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
627
627
|
#declareFunctions(context: PerformanceTraceContext): void {
|
|
628
628
|
const focus = context.getItem();
|
|
629
629
|
const {parsedTrace} = focus;
|
|
630
|
-
const insightSet = focus.primaryInsightSet;
|
|
631
630
|
|
|
632
|
-
this.declareFunction<{insightName: string}, {details: string}>('getInsightDetails', {
|
|
631
|
+
this.declareFunction<{insightSetId: string, insightName: string}, {details: string}>('getInsightDetails', {
|
|
633
632
|
description:
|
|
634
|
-
'Returns detailed information about a specific insight. Use this before commenting on any specific issue to get more information.',
|
|
633
|
+
'Returns detailed information about a specific insight of an insight set. Use this before commenting on any specific issue to get more information.',
|
|
635
634
|
parameters: {
|
|
636
635
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
637
636
|
description: '',
|
|
638
637
|
nullable: false,
|
|
639
638
|
properties: {
|
|
639
|
+
insightSetId: {
|
|
640
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
641
|
+
description:
|
|
642
|
+
'The id for the specific insight set. Only use the ids given in the "Available insight sets" list.',
|
|
643
|
+
nullable: false,
|
|
644
|
+
},
|
|
640
645
|
insightName: {
|
|
641
646
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
642
|
-
description: 'The name of the insight. Only use the insight names given in the Available
|
|
647
|
+
description: 'The name of the insight. Only use the insight names given in the "Available insights" list.',
|
|
643
648
|
nullable: false,
|
|
644
649
|
}
|
|
645
650
|
},
|
|
@@ -647,19 +652,30 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
647
652
|
displayInfoFromArgs: params => {
|
|
648
653
|
return {
|
|
649
654
|
title: lockedString(`Investigating insight ${params.insightName}…`),
|
|
650
|
-
action: `getInsightDetails('${params.insightName}')`
|
|
655
|
+
action: `getInsightDetails('${params.insightSetId}', '${params.insightName}')`
|
|
651
656
|
};
|
|
652
657
|
},
|
|
653
658
|
handler: async params => {
|
|
654
659
|
debugLog('Function call: getInsightDetails', params);
|
|
660
|
+
const insightSet = parsedTrace.insights?.get(params.insightSetId);
|
|
661
|
+
if (!insightSet) {
|
|
662
|
+
const valid = ([...parsedTrace.insights?.values() ?? []])
|
|
663
|
+
.map(
|
|
664
|
+
insightSet => `id: ${insightSet.id}, url: ${insightSet.url}, bounds: ${
|
|
665
|
+
this.#formatter?.serializeBounds(insightSet.bounds)}`)
|
|
666
|
+
.join('; ');
|
|
667
|
+
return {error: `Invalid insight set id. Valid insight set ids are: ${valid}`};
|
|
668
|
+
}
|
|
669
|
+
|
|
655
670
|
const insight = insightSet?.model[params.insightName as keyof Trace.Insights.Types.InsightModels];
|
|
656
671
|
if (!insight) {
|
|
657
|
-
|
|
672
|
+
const valid = Object.keys(insightSet?.model).join(', ');
|
|
673
|
+
return {error: `No insight available. Valid insight names are: ${valid}`};
|
|
658
674
|
}
|
|
659
675
|
|
|
660
676
|
const details = new PerformanceInsightFormatter(focus, insight).formatInsight();
|
|
661
677
|
|
|
662
|
-
const key = `getInsightDetails('${params.insightName}')`;
|
|
678
|
+
const key = `getInsightDetails('${params.insightSetId}', '${params.insightName}')`;
|
|
663
679
|
this.#cacheFunctionResult(focus, key, details);
|
|
664
680
|
return {result: {details}};
|
|
665
681
|
},
|
package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt
CHANGED
|
@@ -504,9 +504,18 @@ IMPORTANT: Never show eventKey to the user.
|
|
|
504
504
|
Title: PerformanceTraceFormatter formatTraceSummary web-dev.json.gz
|
|
505
505
|
Content:
|
|
506
506
|
URL: https://web.dev/cls/
|
|
507
|
-
|
|
507
|
+
Trace bounds: {min: 1020034823047, max: 1020036087961}
|
|
508
508
|
CPU throttling: none
|
|
509
509
|
Network throttling: none
|
|
510
|
+
|
|
511
|
+
# Available insight sets
|
|
512
|
+
|
|
513
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
514
|
+
|
|
515
|
+
## insight set id: 86EB5E5C401E3E17ECE461B3FC627867
|
|
516
|
+
|
|
517
|
+
URL: https://web.dev/cls/
|
|
518
|
+
Bounds: {min: 1020034834921, max: 1020036087961}
|
|
510
519
|
Metrics (lab / observed):
|
|
511
520
|
- LCP: 118 ms, event: (eventKey: r-1802, ts: 1020034953358), nodeId: 209
|
|
512
521
|
- LCP breakdown:
|
|
@@ -537,9 +546,18 @@ Available insights:
|
|
|
537
546
|
Title: PerformanceTraceFormatter formatTraceSummary yahoo-news.json.gz
|
|
538
547
|
Content:
|
|
539
548
|
URL: https://news.yahoo.com/
|
|
540
|
-
|
|
549
|
+
Trace bounds: {min: 157423484442, max: 157427277166}
|
|
541
550
|
CPU throttling: none
|
|
542
551
|
Network throttling: none
|
|
552
|
+
|
|
553
|
+
# Available insight sets
|
|
554
|
+
|
|
555
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
556
|
+
|
|
557
|
+
## insight set id: 513BDA1E9EC088611B53BFF7A859B5DD
|
|
558
|
+
|
|
559
|
+
URL: https://news.yahoo.com/
|
|
560
|
+
Bounds: {min: 157423488682, max: 157427277166}
|
|
543
561
|
Metrics (lab / observed):
|
|
544
562
|
- LCP: 464 ms, event: (eventKey: r-33210, ts: 157423953162), nodeId: 8
|
|
545
563
|
- LCP breakdown:
|
|
@@ -596,12 +614,81 @@ Available insights:
|
|
|
596
614
|
example question: How can I reduce the amount of legacy JavaScript on my page?
|
|
597
615
|
=== end content
|
|
598
616
|
|
|
617
|
+
Title: PerformanceTraceFormatter formatTraceSummary multiple-navigations-render-blocking.json.gz
|
|
618
|
+
Content:
|
|
619
|
+
URL: http://localhost:8080/render-blocking
|
|
620
|
+
Trace bounds: {min: 171605647473, max: 171616667355}
|
|
621
|
+
CPU throttling: 1x
|
|
622
|
+
Network throttling: Fast 3G
|
|
623
|
+
|
|
624
|
+
# Available insight sets
|
|
625
|
+
|
|
626
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
627
|
+
|
|
628
|
+
## insight set id: 8671F33ECE0C8DBAEFBC2F9A2D1D6107
|
|
629
|
+
|
|
630
|
+
URL: http://localhost:8080/render-blocking
|
|
631
|
+
Bounds: {min: 171607579779, max: 171613750571}
|
|
632
|
+
Metrics (lab / observed):
|
|
633
|
+
- LCP: 1317 ms, event: (eventKey: r-6686, ts: 171608897210), nodeId: 10
|
|
634
|
+
- LCP breakdown:
|
|
635
|
+
- TTFB: 10 ms, bounds: {min: 171607579779, max: 171607589981.99997}
|
|
636
|
+
- Render delay: 1,307 ms, bounds: {min: 171607589981.99997, max: 171608897210}
|
|
637
|
+
- CLS: 0.00
|
|
638
|
+
Metrics (field / real users): n/a – no data for this page in CrUX
|
|
639
|
+
Available insights:
|
|
640
|
+
- insight name: LCPBreakdown
|
|
641
|
+
description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.
|
|
642
|
+
relevant trace bounds: {min: 171607579779, max: 171608897210}
|
|
643
|
+
example question: Help me optimize my LCP score
|
|
644
|
+
example question: Which LCP phase was most problematic?
|
|
645
|
+
example question: What can I do to reduce the LCP time for this page load?
|
|
646
|
+
- insight name: RenderBlocking
|
|
647
|
+
description: Requests are blocking the page's initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.
|
|
648
|
+
relevant trace bounds: {min: 171608170438, max: 171608877165}
|
|
649
|
+
example question: Show me the most impactful render blocking requests that I should focus on
|
|
650
|
+
example question: How can I reduce the number of render blocking requests?
|
|
651
|
+
|
|
652
|
+
## insight set id: 1AE2016BBCC48AA090FDAE2CBBA01900
|
|
653
|
+
|
|
654
|
+
URL: http://localhost:8080/render-blocking
|
|
655
|
+
Bounds: {min: 171613750571, max: 171616667355}
|
|
656
|
+
Metrics (lab / observed):
|
|
657
|
+
- LCP: 1310 ms, event: (eventKey: r-15639, ts: 171615060776), nodeId: 18
|
|
658
|
+
- LCP breakdown:
|
|
659
|
+
- TTFB: 3 ms, bounds: {min: 171613750571, max: 171613753188}
|
|
660
|
+
- Render delay: 1,308 ms, bounds: {min: 171613753188, max: 171615060776}
|
|
661
|
+
- CLS: 0.00
|
|
662
|
+
Metrics (field / real users): n/a – no data for this page in CrUX
|
|
663
|
+
Available insights:
|
|
664
|
+
- insight name: LCPBreakdown
|
|
665
|
+
description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.
|
|
666
|
+
relevant trace bounds: {min: 171613750571, max: 171615060776}
|
|
667
|
+
example question: Help me optimize my LCP score
|
|
668
|
+
example question: Which LCP phase was most problematic?
|
|
669
|
+
example question: What can I do to reduce the LCP time for this page load?
|
|
670
|
+
- insight name: RenderBlocking
|
|
671
|
+
description: Requests are blocking the page's initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.
|
|
672
|
+
relevant trace bounds: {min: 171614330544, max: 171615043224}
|
|
673
|
+
example question: Show me the most impactful render blocking requests that I should focus on
|
|
674
|
+
example question: How can I reduce the number of render blocking requests?
|
|
675
|
+
=== end content
|
|
676
|
+
|
|
599
677
|
Title: PerformanceTraceFormatter formatTraceSummary deals with CrUX manager errors
|
|
600
678
|
Content:
|
|
601
679
|
URL: http://localhost/image-delivery-cases.html
|
|
602
|
-
|
|
680
|
+
Trace bounds: {min: 59728641874, max: 59734400108}
|
|
603
681
|
CPU throttling: 1x
|
|
604
682
|
Network throttling: No throttling
|
|
683
|
+
|
|
684
|
+
# Available insight sets
|
|
685
|
+
|
|
686
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
687
|
+
|
|
688
|
+
## insight set id: 9094E106056B51D078CE44F3356FE194
|
|
689
|
+
|
|
690
|
+
URL: http://localhost/image-delivery-cases.html
|
|
691
|
+
Bounds: {min: 59728649746, max: 59734400108}
|
|
605
692
|
Metrics (lab / observed):
|
|
606
693
|
- LCP: 663 ms, event: (eventKey: r-14753, ts: 59729312744), nodeId: 12
|
|
607
694
|
- LCP breakdown:
|
|
@@ -663,9 +750,18 @@ Available insights:
|
|
|
663
750
|
Title: PerformanceTraceFormatter formatTraceSummary image-delivery.json.gz
|
|
664
751
|
Content:
|
|
665
752
|
URL: http://localhost/image-delivery-cases.html
|
|
666
|
-
|
|
753
|
+
Trace bounds: {min: 59728641874, max: 59734400108}
|
|
667
754
|
CPU throttling: 1x
|
|
668
755
|
Network throttling: No throttling
|
|
756
|
+
|
|
757
|
+
# Available insight sets
|
|
758
|
+
|
|
759
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
760
|
+
|
|
761
|
+
## insight set id: 9094E106056B51D078CE44F3356FE194
|
|
762
|
+
|
|
763
|
+
URL: http://localhost/image-delivery-cases.html
|
|
764
|
+
Bounds: {min: 59728649746, max: 59734400108}
|
|
669
765
|
Metrics (lab / observed):
|
|
670
766
|
- LCP: 663 ms, event: (eventKey: r-14753, ts: 59729312744), nodeId: 12
|
|
671
767
|
- LCP breakdown:
|
|
@@ -734,9 +830,18 @@ Available insights:
|
|
|
734
830
|
Title: PerformanceTraceFormatter formatTraceSummary includes INP insight when there is no navigation
|
|
735
831
|
Content:
|
|
736
832
|
URL: https://b2607f8b04800100000289cb1c0a82ba72253000000000000000001.proxy.googlers.com/long-interaction/index.html?x=35
|
|
737
|
-
|
|
833
|
+
Trace bounds: {min: 337943614456, max: 337947260898}
|
|
738
834
|
CPU throttling: none
|
|
739
835
|
Network throttling: none
|
|
836
|
+
|
|
837
|
+
# Available insight sets
|
|
838
|
+
|
|
839
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
840
|
+
|
|
841
|
+
## insight set id: NO_NAVIGATION
|
|
842
|
+
|
|
843
|
+
URL: https://b2607f8b04800100000289cb1c0a82ba72253000000000000000001.proxy.googlers.com/long-interaction/index.html?x=35
|
|
844
|
+
Bounds: {min: 337943614456, max: 337947260898}
|
|
740
845
|
Metrics (lab / observed):
|
|
741
846
|
- INP: 139 ms, event: (eventKey: s-3347, ts: 337944870984)
|
|
742
847
|
- CLS: 0.00
|
|
@@ -116,62 +116,69 @@ export class PerformanceTraceFormatter {
|
|
|
116
116
|
|
|
117
117
|
formatTraceSummary(): string {
|
|
118
118
|
const parsedTrace = this.#parsedTrace;
|
|
119
|
-
const insightSet = this.#insightSet;
|
|
120
119
|
const traceMetadata = this.#parsedTrace.metadata;
|
|
121
120
|
const data = parsedTrace.data;
|
|
122
121
|
|
|
123
122
|
const parts = [];
|
|
124
123
|
|
|
125
|
-
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
126
|
-
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
127
|
-
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
128
|
-
|
|
129
124
|
parts.push(`URL: ${data.Meta.mainFrameURL}`);
|
|
130
|
-
parts.push(`
|
|
125
|
+
parts.push(`Trace bounds: ${this.serializeBounds(data.Meta.traceBounds)}`);
|
|
131
126
|
parts.push('CPU throttling: ' + (traceMetadata.cpuThrottling ? `${traceMetadata.cpuThrottling}x` : 'none'));
|
|
132
127
|
parts.push(`Network throttling: ${traceMetadata.networkThrottling ?? 'none'}`);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
128
|
+
|
|
129
|
+
parts.push('\n# Available insight sets\n');
|
|
130
|
+
parts.push(
|
|
131
|
+
'The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.');
|
|
132
|
+
|
|
133
|
+
for (const insightSet of parsedTrace.insights?.values() ?? []) {
|
|
134
|
+
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
135
|
+
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
136
|
+
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
137
|
+
|
|
138
|
+
parts.push(`\n## insight set id: ${insightSet.id}\n`);
|
|
139
|
+
parts.push(`URL: ${insightSet.url}`);
|
|
140
|
+
parts.push(`Bounds: ${this.serializeBounds(insightSet.bounds)}`);
|
|
141
|
+
if (lcp || cls || inp) {
|
|
142
|
+
parts.push('Metrics (lab / observed):');
|
|
143
|
+
if (lcp) {
|
|
144
|
+
const nodeId = insightSet?.model.LCPBreakdown.lcpEvent?.args.data?.nodeId;
|
|
145
|
+
const nodeIdText = nodeId !== undefined ? `, nodeId: ${nodeId}` : '';
|
|
146
|
+
parts.push(
|
|
147
|
+
` - LCP: ${Math.round(lcp.value / 1000)} ms, event: ${this.serializeEvent(lcp.event)}${nodeIdText}`);
|
|
148
|
+
const subparts = insightSet?.model.LCPBreakdown.subparts;
|
|
149
|
+
if (subparts) {
|
|
150
|
+
const serializeSubpart = (subpart: Trace.Insights.Models.LCPBreakdown.Subpart): string => {
|
|
151
|
+
return `${micros(subpart.range)}, bounds: ${this.serializeBounds(subpart)}`;
|
|
152
|
+
};
|
|
153
|
+
parts.push(' - LCP breakdown:');
|
|
154
|
+
parts.push(` - TTFB: ${serializeSubpart(subparts.ttfb)}`);
|
|
155
|
+
if (subparts.loadDelay !== undefined) {
|
|
156
|
+
parts.push(` - Load delay: ${serializeSubpart(subparts.loadDelay)}`);
|
|
157
|
+
}
|
|
158
|
+
if (subparts.loadDuration !== undefined) {
|
|
159
|
+
parts.push(` - Load duration: ${serializeSubpart(subparts.loadDuration)}`);
|
|
160
|
+
}
|
|
161
|
+
parts.push(` - Render delay: ${serializeSubpart(subparts.renderDelay)}`);
|
|
152
162
|
}
|
|
153
|
-
parts.push(` - Render delay: ${serializeSubpart(subparts.renderDelay)}`);
|
|
154
163
|
}
|
|
164
|
+
if (inp) {
|
|
165
|
+
parts.push(` - INP: ${Math.round(inp.value / 1000)} ms, event: ${this.serializeEvent(inp.event)}`);
|
|
166
|
+
}
|
|
167
|
+
if (cls) {
|
|
168
|
+
const eventText = cls.worstClusterEvent ? `, event: ${this.serializeEvent(cls.worstClusterEvent)}` : '';
|
|
169
|
+
parts.push(` - CLS: ${cls.value.toFixed(2)}${eventText}`);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
parts.push('Metrics (lab / observed): n/a');
|
|
155
173
|
}
|
|
156
|
-
if (inp) {
|
|
157
|
-
parts.push(` - INP: ${Math.round(inp.value / 1000)} ms, event: ${this.serializeEvent(inp.event)}`);
|
|
158
|
-
}
|
|
159
|
-
if (cls) {
|
|
160
|
-
const eventText = cls.worstClusterEvent ? `, event: ${this.serializeEvent(cls.worstClusterEvent)}` : '';
|
|
161
|
-
parts.push(` - CLS: ${cls.value.toFixed(2)}${eventText}`);
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
parts.push('Metrics (lab / observed): n/a');
|
|
165
|
-
}
|
|
166
174
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
175
|
+
const cruxParts = insightSet && this.#getCruxTraceSummary(insightSet);
|
|
176
|
+
if (cruxParts?.length) {
|
|
177
|
+
parts.push(...cruxParts);
|
|
178
|
+
} else {
|
|
179
|
+
parts.push('Metrics (field / real users): n/a – no data for this page in CrUX');
|
|
180
|
+
}
|
|
173
181
|
|
|
174
|
-
if (insightSet) {
|
|
175
182
|
parts.push('Available insights:');
|
|
176
183
|
for (const [insightName, model] of Object.entries(insightSet.model)) {
|
|
177
184
|
if (model.state === 'pass') {
|
|
@@ -202,8 +209,6 @@ export class PerformanceTraceFormatter {
|
|
|
202
209
|
const insightPartsText = insightParts.join('\n ');
|
|
203
210
|
parts.push(` - ${insightPartsText}`);
|
|
204
211
|
}
|
|
205
|
-
} else {
|
|
206
|
-
parts.push('Available insights: none');
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
return parts.join('\n');
|
|
@@ -13,7 +13,7 @@ export class ProfileNode {
|
|
|
13
13
|
id: number;
|
|
14
14
|
parent: ProfileNode|null;
|
|
15
15
|
children: this[];
|
|
16
|
-
|
|
16
|
+
originalFunctionName: string|null = null;
|
|
17
17
|
depth!: number;
|
|
18
18
|
deoptReason!: string|null;
|
|
19
19
|
constructor(callFrame: Protocol.Runtime.CallFrame) {
|
|
@@ -22,7 +22,6 @@ export class ProfileNode {
|
|
|
22
22
|
this.self = 0;
|
|
23
23
|
this.total = 0;
|
|
24
24
|
this.id = 0;
|
|
25
|
-
this.functionName = callFrame.functionName;
|
|
26
25
|
this.parent = null;
|
|
27
26
|
this.children = [];
|
|
28
27
|
}
|
|
@@ -43,11 +42,12 @@ export class ProfileNode {
|
|
|
43
42
|
return this.callFrame.columnNumber;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
get functionName(): string {
|
|
46
|
+
return this.originalFunctionName ?? this.callFrame.functionName;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setOriginalFunctionName(name: string|null): void {
|
|
50
|
+
this.originalFunctionName = name;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -173,7 +173,7 @@ export class SourceMapsResolver extends EventTarget {
|
|
|
173
173
|
const resolvedFunctionName =
|
|
174
174
|
await SourceMapScopes.NamesResolver.resolveProfileFrameFunctionName(node.callFrame, target);
|
|
175
175
|
updatedMappings ||= Boolean(resolvedFunctionName);
|
|
176
|
-
node.
|
|
176
|
+
node.setOriginalFunctionName(resolvedFunctionName);
|
|
177
177
|
|
|
178
178
|
const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
179
179
|
const script = debuggerModel?.scriptForId(node.scriptId) || null;
|
|
@@ -12,6 +12,7 @@ import type * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
|
12
12
|
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
|
13
13
|
import * as uiI18n from '../../ui/i18n/i18n.js';
|
|
14
14
|
import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
|
|
15
|
+
import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
|
|
15
16
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
16
17
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
17
18
|
|
|
@@ -207,7 +208,7 @@ export class StorageView extends UI.Widget.VBox {
|
|
|
207
208
|
this.clearButton.id = 'storage-view-clear-button';
|
|
208
209
|
clearButtonSection.appendChild(this.clearButton);
|
|
209
210
|
|
|
210
|
-
const includeThirdPartyCookiesCheckbox =
|
|
211
|
+
const includeThirdPartyCookiesCheckbox = SettingsUI.SettingsUI.createSettingCheckbox(
|
|
211
212
|
i18nString(UIStrings.includingThirdPartyCookies), this.includeThirdPartyCookiesSetting);
|
|
212
213
|
includeThirdPartyCookiesCheckbox.classList.add('include-third-party-cookies');
|
|
213
214
|
clearButtonSection.appendChild(includeThirdPartyCookiesCheckbox);
|
|
@@ -280,7 +281,7 @@ export class StorageView extends UI.Widget.VBox {
|
|
|
280
281
|
const row = section.appendRow();
|
|
281
282
|
const setting = this.settings.get(settingName);
|
|
282
283
|
if (setting) {
|
|
283
|
-
row.appendChild(
|
|
284
|
+
row.appendChild(SettingsUI.SettingsUI.createSettingCheckbox(title, setting));
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
287
|
|