chrome-devtools-frontend 1.0.1519267 → 1.0.1520535

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.
Files changed (94) hide show
  1. package/config/owner/COMMON_OWNERS +1 -2
  2. package/config/typescript/tsconfig.eslint.json +12 -1
  3. package/docs/ui_engineering.md +1011 -0
  4. package/front_end/core/host/GdpClient.ts +26 -5
  5. package/front_end/core/sdk/NetworkManager.ts +1 -0
  6. package/front_end/core/sdk/NetworkRequest.ts +10 -0
  7. package/front_end/entrypoints/main/MainImpl.ts +6 -1
  8. package/front_end/entrypoints/main/main-meta.ts +3 -3
  9. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +50 -48
  10. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
  11. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +128 -30
  12. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +98 -63
  13. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
  14. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +36 -21
  15. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
  16. package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
  17. package/front_end/models/ai_assistance/performance/AIContext.ts +62 -7
  18. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -5
  19. package/front_end/models/badges/Badge.ts +6 -1
  20. package/front_end/models/badges/StarterBadge.ts +5 -0
  21. package/front_end/models/badges/UserBadges.ts +5 -4
  22. package/front_end/models/javascript_metadata/NativeFunctions.js +5 -1
  23. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +14 -7
  24. package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
  25. package/front_end/panels/ai_assistance/components/ChatView.ts +45 -69
  26. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +47 -1
  27. package/front_end/panels/ai_assistance/components/chatView.css +13 -1
  28. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  29. package/front_end/panels/animation/animationTimeline.css +4 -0
  30. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
  31. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
  32. package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
  33. package/front_end/panels/console/ConsolePrompt.ts +6 -0
  34. package/front_end/panels/console/ConsoleView.ts +4 -2
  35. package/front_end/panels/coverage/CoverageListView.ts +146 -198
  36. package/front_end/panels/coverage/CoverageView.ts +48 -18
  37. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
  38. package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
  39. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  40. package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
  41. package/front_end/panels/search/SearchResultsPane.ts +48 -15
  42. package/front_end/panels/search/SearchView.ts +33 -30
  43. package/front_end/panels/search/searchView.css +0 -2
  44. package/front_end/panels/settings/components/SyncSection.ts +4 -4
  45. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
  46. package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
  47. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
  48. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
  49. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
  50. package/front_end/panels/timeline/TimelinePanel.ts +2 -0
  51. package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
  52. package/front_end/panels/timeline/components/ExportTraceOptions.ts +56 -4
  53. package/front_end/panels/timeline/components/exportTraceOptions.css +5 -0
  54. package/front_end/third_party/chromium/README.chromium +1 -1
  55. package/front_end/third_party/lighthouse/README.chromium +8 -1
  56. package/front_end/third_party/puppeteer/README.chromium +2 -2
  57. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  58. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
  65. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  67. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  68. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
  70. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  71. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +4 -4
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
  77. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
  78. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
  79. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  80. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  81. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
  83. package/front_end/third_party/puppeteer/package/package.json +3 -2
  84. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  85. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
  86. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
  87. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  88. package/front_end/third_party/puppeteer/package/src/util/Function.ts +1 -1
  89. package/front_end/tsconfig.json +12 -1
  90. package/front_end/ui/legacy/InspectorView.ts +86 -13
  91. package/front_end/ui/legacy/TabbedPane.ts +2 -1
  92. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
  93. package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
  94. package/package.json +1 -1
@@ -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 `https://creativetouchrotherham.co.uk/images/creative-touch-home/creative_touch_rotherham_homehero/creative_touch_rotherham_homehero_700.webp`.
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, ts: 397824185142).
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 `https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg`.
71
+ The LCP element is an image fetched from https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg (eventKey: s-1314, ts: 122411037986).
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 `http://localhost:8787/lcp-discovery-delay/lcp-image.jpg`.
189
+ The LCP element is an image fetched from http://localhost:8787/lcp-discovery-delay/lcp-image.jpg (eventKey: s-25281, ts: 197696859337).
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 (https://fonts.gstatic.com/s/specialgothicexpandedone/v2/IurO6Zxk74-YaYk1r3HOet4g75ENmBxUmOK61tA0Iu5QmJF_.woff2).
313
+ - A font that was loaded over the network: https://fonts.gstatic.com/s/specialgothicexpandedone/v2/IurO6Zxk74-YaYk1r3HOet4g75ENmBxUmOK61tA0Iu5QmJF_.woff2 (eventKey: s-1158, ts: 1355335690947).
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, ts: 1355336697136)).
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, ts: 1355336697136)).
329
329
  ### Layout shift 5:
330
330
  - Start time: 2,343 ms
331
331
  - Score: 0.3396
@@ -334,7 +334,105 @@ Layout shifts in this cluster:
334
334
  ## Estimated savings: none
335
335
 
336
336
  ## External resources:
337
- - https://wdeb.dev/articles/cls
337
+ - https://web.dev/articles/cls
338
+ - https://web.dev/articles/optimize-cls
339
+ === end content
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://web.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://web.dev/articles/cls
338
436
  - https://web.dev/articles/optimize-cls
339
437
  === end content
340
438
 
@@ -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, ts: 157423742567) - 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, ts: 157423743431) - 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, ts: 157423760794) - 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, ts: 157426026656) - 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, ts: 157423742450) - 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, ts: 157424128231) - 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, ts: 157423489126) - 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, ts: 157423761978) - 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, ts: 409057956748), 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, ts: 409057956250), 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, ts: 409057957711), 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, ts: 409057958585), 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, ts: 409057959655), 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, ts: 409057956530), 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, ts: 59728701403)
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, ts: 59728702014)
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, ts: 59728702737)
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, ts: 59728702313)
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, ts: 59728702539)
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, ts: 566777570990) (5,006 ms) (longest chain)
954
+ - http://localhost:8787/lcp-iframes/app.js (eventKey: s-7225, ts: 566782574106) (5,015 ms) (longest chain)
955
+ - http://localhost:8787/lcp-iframes/app.css (eventKey: s-7213, ts: 566782573909) (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, ts: 658799777502)
983
1081
  - Cache Time to Live (TTL): 600 seconds
984
1082
  - Wasted bytes: 0 B
985
1083
 
@@ -39,14 +39,15 @@ function getLCPData(parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string,
39
39
  };
40
40
  }
41
41
 
42
- export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
42
+ export class PerformanceInsightFormatter {
43
+ #traceFormatter: PerformanceTraceFormatter;
43
44
  #insight: Trace.Insights.Types.InsightModel;
44
45
  #parsedTrace: Trace.TraceModel.ParsedTrace;
45
46
 
46
47
  constructor(focus: AgentFocus, insight: Trace.Insights.Types.InsightModel) {
47
- super(focus);
48
+ this.#traceFormatter = new PerformanceTraceFormatter(focus);
48
49
  this.#insight = insight;
49
- this.#parsedTrace = focus.data.parsedTrace;
50
+ this.#parsedTrace = focus.parsedTrace;
50
51
  }
51
52
 
52
53
  #formatMilli(x?: number): string {
@@ -63,6 +64,27 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
63
64
  return this.#formatMilli(Trace.Helpers.Timing.microToMilli(x as Trace.Types.Timing.Micro));
64
65
  }
65
66
 
67
+ #formatRequestUrl(request: Trace.Types.Events.SyntheticNetworkRequest): string {
68
+ return `${request.args.data.url} ${this.#traceFormatter.serializeEvent(request)}`;
69
+ }
70
+
71
+ #formatScriptUrl(script: Trace.Handlers.ModelHandlers.Scripts.Script): string {
72
+ if (script.request) {
73
+ return this.#formatRequestUrl(script.request);
74
+ }
75
+
76
+ return script.url ?? script.sourceUrl ?? script.scriptId;
77
+ }
78
+
79
+ #formatUrl(url: string): string {
80
+ const request = this.#parsedTrace.data.NetworkRequests.byTime.find(request => request.args.data.url === url);
81
+ if (request) {
82
+ return this.#formatRequestUrl(request);
83
+ }
84
+
85
+ return url;
86
+ }
87
+
66
88
  /**
67
89
  * Information about LCP which we pass to the LLM for all insights that relate to LCP.
68
90
  */
@@ -81,16 +103,17 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
81
103
  }
82
104
 
83
105
  const {metricScore, lcpRequest, lcpEvent} = data;
84
- const theLcpElement =
85
- lcpEvent.args.data?.nodeName ? `The LCP element (${lcpEvent.args.data.nodeName})` : 'The LCP element';
106
+ const theLcpElement = lcpEvent.args.data?.nodeName ?
107
+ `The LCP element (${lcpEvent.args.data.nodeName}, nodeId: ${lcpEvent.args.data.nodeId})` :
108
+ 'The LCP element';
86
109
  const parts: string[] = [
87
110
  `The Largest Contentful Paint (LCP) time for this navigation was ${this.#formatMicro(metricScore.timing)}.`,
88
111
  ];
89
112
 
90
113
  if (lcpRequest) {
91
- parts.push(`${theLcpElement} is an image fetched from \`${lcpRequest.args.data.url}\`.`);
92
- const request =
93
- this.formatNetworkRequests([lcpRequest], {verbose: true, customTitle: 'LCP resource network request'});
114
+ parts.push(`${theLcpElement} is an image fetched from ${this.#formatRequestUrl(lcpRequest)}.`);
115
+ const request = this.#traceFormatter.formatNetworkRequests(
116
+ [lcpRequest], {verbose: true, customTitle: 'LCP resource network request'});
94
117
  parts.push(request);
95
118
  } else {
96
119
  parts.push(`${theLcpElement} is text and was not fetched from the network.`);
@@ -203,7 +226,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
203
226
  let output = 'The following resources were associated with ineffficient cache policies:\n';
204
227
 
205
228
  for (const entry of insight.requests) {
206
- output += `\n- ${entry.request.args.data.url}`;
229
+ output += `\n- ${this.#formatRequestUrl(entry.request)}`;
207
230
  output += `\n - Cache Time to Live (TTL): ${entry.ttl} seconds`;
208
231
  output += `\n - Wasted bytes: ${bytes(entry.wastedBytes)}`;
209
232
  }
@@ -212,6 +235,57 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
212
235
  return output;
213
236
  }
214
237
 
238
+ #formatLayoutShift(
239
+ shift: Trace.Types.Events.SyntheticLayoutShift, index: number,
240
+ rootCauses?: Trace.Insights.Models.CLSCulprits.LayoutShiftRootCausesData): string {
241
+ const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
242
+
243
+ const potentialRootCauses: string[] = [];
244
+ if (rootCauses) {
245
+ rootCauses.iframes.forEach(
246
+ iframe => potentialRootCauses.push(
247
+ `- An iframe (id: ${iframe.frame}, url: ${iframe.url ?? 'unknown'} was injected into the page)`));
248
+ rootCauses.webFonts.forEach(req => {
249
+ potentialRootCauses.push(`- A font that was loaded over the network: ${this.#formatRequestUrl(req)}.`);
250
+ });
251
+ rootCauses.nonCompositedAnimations.forEach(nonCompositedFailure => {
252
+ potentialRootCauses.push('- A non-composited animation:');
253
+
254
+ const animationInfoOutput = [];
255
+ potentialRootCauses.push(`- non-composited animation: \`${nonCompositedFailure.name || '(unnamed)'}\``);
256
+ if (nonCompositedFailure.name) {
257
+ animationInfoOutput.push(`Animation name: ${nonCompositedFailure.name}`);
258
+ }
259
+ if (nonCompositedFailure.unsupportedProperties) {
260
+ animationInfoOutput.push('Unsupported CSS properties:');
261
+ animationInfoOutput.push('- ' + nonCompositedFailure.unsupportedProperties.join(', '));
262
+ }
263
+ animationInfoOutput.push('Failure reasons:');
264
+ animationInfoOutput.push(' - ' + nonCompositedFailure.failureReasons.join(', '));
265
+
266
+ // Extra padding to the detail to not mess up the indentation.
267
+ potentialRootCauses.push(animationInfoOutput.map(l => ' '.repeat(4) + l).join('\n'));
268
+ });
269
+
270
+ rootCauses.unsizedImages.forEach(img => {
271
+ // TODO(b/413284569): if we store a nice human readable name for this
272
+ // image in the trace metadata, we can do something much nicer here.
273
+ const url = img.paintImageEvent.args.data.url;
274
+ const nodeName = img.paintImageEvent.args.data.nodeName;
275
+ const extraText = url ? `url: ${this.#formatUrl(url)}` : `id: ${img.backendNodeId}`;
276
+ potentialRootCauses.push(`- An unsized image (${nodeName}) (${extraText}).`);
277
+ });
278
+ }
279
+ const rootCauseText = potentialRootCauses.length ? `- Potential root causes:\n ${potentialRootCauses.join('\n')}` :
280
+ '- No potential root causes identified';
281
+
282
+ const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
283
+ return `### Layout shift ${index + 1}:
284
+ - Start time: ${millis(startTime)}
285
+ - Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
286
+ ${rootCauseText}`;
287
+ }
288
+
215
289
  /**
216
290
  * Create an AI prompt string out of the CLS Culprits Insight model to use with Ask AI.
217
291
  * @param insight The CLS Culprits Model to query.
@@ -220,7 +294,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
220
294
  formatClsCulpritsInsight(insight: Trace.Insights.Models.CLSCulprits.CLSCulpritsInsightModel): string {
221
295
  const {worstCluster, shifts} = insight;
222
296
  if (!worstCluster) {
223
- return '';
297
+ return 'No layout shifts were found.';
224
298
  }
225
299
 
226
300
  const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
@@ -231,7 +305,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
231
305
  } as const;
232
306
 
233
307
  const shiftsFormatted = worstCluster.events.map((layoutShift, index) => {
234
- return TraceEventFormatter.layoutShift(layoutShift, index, this.#parsedTrace, shifts.get(layoutShift));
308
+ return this.#formatLayoutShift(layoutShift, index, shifts.get(layoutShift));
235
309
  });
236
310
 
237
311
  return `The worst layout shift cluster was the cluster that started at ${
@@ -272,7 +346,7 @@ ${shiftsFormatted.join('\n')}`;
272
346
 
273
347
  return `${this.#lcpMetricSharedContext()}
274
348
 
275
- ${this.formatNetworkRequests([documentRequest], {
349
+ ${this.#traceFormatter.formatNetworkRequests([documentRequest], {
276
350
  verbose: true,
277
351
  customTitle: 'Document network request'
278
352
  })}
@@ -384,8 +458,9 @@ Duplication grouped by Node modules: ${filesFormatted}`;
384
458
  const url = new Common.ParsedURL.ParsedURL(font.request.args.data.url);
385
459
  fontName = url.isValid ? url.lastPathComponent : '(not available)';
386
460
  }
387
- output += `\n - Font name: ${fontName}, URL: ${font.request.args.data.url}, Property 'font-display' set to: '${
388
- font.display}', Wasted time: ${this.#formatMilli(font.wastedTime)}.`;
461
+ output += `\n - Font name: ${fontName}, URL: ${
462
+ this.#formatRequestUrl(font.request)}, Property 'font-display' set to: '${font.display}', Wasted time: ${
463
+ this.#formatMilli(font.wastedTime)}.`;
389
464
  }
390
465
 
391
466
  output += '\n\n' + Trace.Insights.Models.FontDisplay.UIStrings.description;
@@ -469,7 +544,7 @@ Duplication grouped by Node modules: ${filesFormatted}`;
469
544
  })
470
545
  .join('\n');
471
546
 
472
- return `### ${image.request.args.data.url}
547
+ return `### ${this.#formatRequestUrl(image.request)}
473
548
  - Potential savings: ${bytes(image.byteSavings)}
474
549
  - Optimizations:\n${optimizations}`;
475
550
  })
@@ -580,7 +655,9 @@ ${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED'
580
655
 
581
656
  const filesFormatted =
582
657
  Array.from(legacyJavaScriptResults)
583
- .map(([script, result]) => `\n- Script: ${script.url} - Wasted bytes: ${result.estimatedByteSavings} bytes
658
+ .map(
659
+ ([script, result]) =>
660
+ `\n- Script: ${this.#formatScriptUrl(script)} - Wasted bytes: ${result.estimatedByteSavings} bytes
584
661
  Matches:
585
662
  ${result.matches.map(match => `Line: ${match.line}, Column: ${match.column}, Name: ${match.name}`).join('\n')}`)
586
663
  .join('\n');
@@ -598,8 +675,8 @@ ${filesFormatted}`;
598
675
  */
599
676
  formatModernHttpInsight(insight: Trace.Insights.Models.ModernHTTP.ModernHTTPInsightModel): string {
600
677
  const requestSummary = (insight.http1Requests.length === 1) ?
601
- this.formatNetworkRequests(insight.http1Requests, {verbose: true}) :
602
- this.formatNetworkRequests(insight.http1Requests);
678
+ this.#traceFormatter.formatNetworkRequests(insight.http1Requests, {verbose: true}) :
679
+ this.#traceFormatter.formatNetworkRequests(insight.http1Requests);
603
680
 
604
681
  if (requestSummary.length === 0) {
605
682
  return 'There are no requests that were served over a legacy HTTP protocol.';
@@ -631,7 +708,7 @@ ${requestSummary}`;
631
708
  function formatNode(
632
709
  this: PerformanceInsightFormatter, node: Trace.Insights.Models.NetworkDependencyTree.CriticalRequestNode,
633
710
  indent: string): string {
634
- const url = node.request.args.data.url;
711
+ const url = this.#formatRequestUrl(node.request);
635
712
  const time = this.#formatMicro(node.timeFromInitialRequest);
636
713
  const isLongest = node.isLongest ? ' (longest chain)' : '';
637
714
  let nodeString = `${indent}- ${url} (${time})${isLongest}\n`;
@@ -696,7 +773,7 @@ ${requestSummary}`;
696
773
  * @returns a string formatted for sending to Ask AI.
697
774
  */
698
775
  formatRenderBlockingInsight(insight: Trace.Insights.Models.RenderBlocking.RenderBlockingInsightModel): string {
699
- const requestSummary = this.formatNetworkRequests(insight.renderBlockingRequests);
776
+ const requestSummary = this.#traceFormatter.formatNetworkRequests(insight.renderBlockingRequests);
700
777
 
701
778
  if (requestSummary.length === 0) {
702
779
  return 'There are no network requests that are render blocking.';
@@ -934,7 +1011,7 @@ ${this.#links()}`;
934
1011
  #links(): string {
935
1012
  switch (this.#insight.insightKey) {
936
1013
  case 'CLSCulprits':
937
- return `- https://wdeb.dev/articles/cls
1014
+ return `- https://web.dev/articles/cls
938
1015
  - https://web.dev/articles/optimize-cls`;
939
1016
  case 'DocumentLatency':
940
1017
  return '- https://web.dev/articles/optimize-ttfb';
@@ -1065,45 +1142,3 @@ Polyfills and transforms enable older browsers to use new JavaScript features. H
1065
1142
  }
1066
1143
  }
1067
1144
  }
1068
-
1069
- export class TraceEventFormatter {
1070
- static layoutShift(
1071
- shift: Trace.Types.Events.SyntheticLayoutShift, index: number, parsedTrace: Trace.TraceModel.ParsedTrace,
1072
- rootCauses?: Trace.Insights.Models.CLSCulprits.LayoutShiftRootCausesData): string {
1073
- const baseTime = parsedTrace.data.Meta.traceBounds.min;
1074
-
1075
- const potentialRootCauses: string[] = [];
1076
- if (rootCauses) {
1077
- rootCauses.iframes.forEach(
1078
- iframe => potentialRootCauses.push(
1079
- `An iframe (id: ${iframe.frame}, url: ${iframe.url ?? 'unknown'} was injected into the page)`));
1080
- rootCauses.webFonts.forEach(req => {
1081
- potentialRootCauses.push(`A font that was loaded over the network (${req.args.data.url}).`);
1082
- });
1083
- // TODO(b/413285103): use the nice strings for non-composited animations.
1084
- // The code for this lives in TimelineUIUtils but that cannot be used
1085
- // within models. We should move it and then expose the animations info
1086
- // more nicely.
1087
- rootCauses.nonCompositedAnimations.forEach(_ => {
1088
- potentialRootCauses.push('A non composited animation.');
1089
- });
1090
- rootCauses.unsizedImages.forEach(img => {
1091
- // TODO(b/413284569): if we store a nice human readable name for this
1092
- // image in the trace metadata, we can do something much nicer here.
1093
- const url = img.paintImageEvent.args.data.url;
1094
- const nodeName = img.paintImageEvent.args.data.nodeName;
1095
- const extraText = url ? `url: ${url}` : `id: ${img.backendNodeId}`;
1096
- potentialRootCauses.push(`An unsized image (${nodeName}) (${extraText}).`);
1097
- });
1098
- }
1099
- const rootCauseText = potentialRootCauses.length ?
1100
- `- Potential root causes:\n - ${potentialRootCauses.join('\n - ')}` :
1101
- '- No potential root causes identified';
1102
-
1103
- const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
1104
- return `### Layout shift ${index + 1}:
1105
- - Start time: ${millis(startTime)}
1106
- - Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
1107
- ${rootCauseText}`;
1108
- }
1109
- }