webperf-snippets 0.2.0 → 0.4.0

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 (73) hide show
  1. package/README.md +142 -14
  2. package/package.json +1 -1
  3. package/snippets/CoreWebVitals/CLS.js +29 -15
  4. package/snippets/CoreWebVitals/INP.js +14 -7
  5. package/snippets/CoreWebVitals/LCP-Image-Entropy.js +29 -11
  6. package/snippets/CoreWebVitals/LCP-Subparts.js +4 -0
  7. package/snippets/CoreWebVitals/LCP-Trail.js +14 -3
  8. package/snippets/CoreWebVitals/LCP-Video-Candidate.js +20 -2
  9. package/snippets/CoreWebVitals/LCP.js +4 -2
  10. package/snippets/DevTools-Overrides/Fetch-XHR-Timeline-read.js +9 -2
  11. package/snippets/Interaction/DOM-Size-and-Depth.js +134 -0
  12. package/snippets/Interaction/Forced-Synchronous-Layout.js +33 -7
  13. package/snippets/Interaction/Input-Latency-Breakdown.js +45 -1
  14. package/snippets/Interaction/Interactions.js +16 -5
  15. package/snippets/Interaction/Layout-Shift-Loading-and-Interaction.js +44 -13
  16. package/snippets/Interaction/Long-Animation-Frames-Helpers.js +28 -1
  17. package/snippets/Interaction/Long-Animation-Frames-Script-Attribution.js +8 -0
  18. package/snippets/Interaction/Long-Animation-Frames.js +31 -2
  19. package/snippets/Interaction/LongTask.js +37 -5
  20. package/snippets/Interaction/Scroll-Performance.js +40 -0
  21. package/snippets/Interaction/WORKFLOWS.md +9 -0
  22. package/snippets/Loading/Back-Forward-Cache.js +174 -381
  23. package/snippets/Loading/CSS-Media-Queries-Analysis.js +76 -44
  24. package/snippets/Loading/Cache-Strategy-Analysis.js +141 -43
  25. package/snippets/Loading/Compression-Audit.js +172 -0
  26. package/snippets/Loading/Content-Visibility.js +8 -3
  27. package/snippets/Loading/Critical-CSS-Detection.js +8 -6
  28. package/snippets/Loading/Event-Processing-Time.js +15 -2
  29. package/snippets/Loading/FCP.js +39 -5
  30. package/snippets/Loading/Find-Above-The-Fold-Lazy-Loaded-Images.js +1 -1
  31. package/snippets/Loading/Find-non-Lazy-Loaded-Images-outside-of-the-viewport.js +7 -5
  32. package/snippets/Loading/First-And-Third-Party-Script-Info.js +58 -20
  33. package/snippets/Loading/First-And-Third-Party-Script-Timings.js +46 -13
  34. package/snippets/Loading/Fonts-Preloaded-Loaded-and-used-above-the-fold.js +53 -4
  35. package/snippets/Loading/Inline-CSS-Info-and-Size.js +8 -6
  36. package/snippets/Loading/Inline-Script-Info-and-Size.js +14 -7
  37. package/snippets/Loading/JS-Execution-Time-Breakdown.js +23 -10
  38. package/snippets/Loading/Priority-Hints-Audit.js +4 -1
  39. package/snippets/Loading/Resource-Hints-Validation.js +44 -9
  40. package/snippets/Loading/Resource-Hints.js +29 -8
  41. package/snippets/Loading/SSR-Hydration-Data-Analysis.js +77 -8
  42. package/snippets/Loading/Script-Loading.js +72 -24
  43. package/snippets/Loading/Server-Timing-Early-Hints.js +126 -0
  44. package/snippets/Loading/Service-Worker-Analysis.js +229 -53
  45. package/snippets/Loading/Speculation-Rules-Inspector.js +134 -0
  46. package/snippets/Loading/TTFB-Resources.js +86 -18
  47. package/snippets/Loading/TTFB-Sub-Parts.js +9 -2
  48. package/snippets/Loading/TTFB.js +3 -2
  49. package/snippets/Loading/Third-Party-Impact-by-Domain.js +244 -0
  50. package/snippets/Loading/Validate-Preload-Async-Defer-Scripts.js +21 -3
  51. package/snippets/Loading/WORKFLOWS.md +47 -1
  52. package/snippets/Loading/Webfont-Usage-Analyzer.js +332 -0
  53. package/snippets/Media/Image-Element-Audit.js +74 -11
  54. package/snippets/Media/Oversized-Images.js +217 -0
  55. package/snippets/Media/SVG-Embedded-Bitmap-Analysis.js +18 -3
  56. package/snippets/Media/WORKFLOWS.md +22 -0
  57. package/snippets/Resources/Network-Bandwidth-Connection-Quality.js +7 -0
  58. package/snippets/SCHEMA.md +1179 -0
  59. package/snippets/_shared/helpers.js +61 -0
  60. package/src/bin.js +72 -45
  61. package/src/crux.js +84 -0
  62. package/src/decision-tree.js +55 -7
  63. package/src/interactions.js +13 -3
  64. package/src/load-snippet.js +1 -1
  65. package/src/report-to.js +46 -0
  66. package/src/reporters/human.js +43 -5
  67. package/src/reporters/markdown.js +27 -1
  68. package/src/runner.js +75 -21
  69. package/src/snippet-names.js +89 -0
  70. package/src/tracking.js +6 -0
  71. package/src/workflows/audit.js +17 -0
  72. package/src/workflows/interaction.js +30 -0
  73. package/src/workflows/loading.js +9 -0
@@ -188,6 +188,38 @@
188
188
  return results;
189
189
  };
190
190
 
191
+ // Findings as homogeneous items and actionable issues (same value at start and in the summary)
192
+ const buildFindings = (css) => {
193
+ const seen = new Set();
194
+ const items = [];
195
+ const add = (kind, target, detail) => {
196
+ const key = `${kind}|${target}|${detail}`;
197
+ if (seen.has(key)) return;
198
+ seen.add(key);
199
+ items.push({ kind, target, detail });
200
+ };
201
+ nonPassiveListeners.forEach((l) =>
202
+ add("non-passive-listener", `${l.element}${l.id ? `#${l.id}` : ""}`, l.type)
203
+ );
204
+ css.willChangeElements.forEach((e) => add("will-change", e.element, e.value));
205
+ css.overscrollElements.forEach((e) => add("overscroll", e.element, e.value));
206
+
207
+ const issues = [];
208
+ if (nonPassiveListeners.length > 0) {
209
+ issues.push({
210
+ severity: "warning",
211
+ message: `${nonPassiveListeners.length} non-passive scroll or touch listener(s). Add { passive: true } so scrolling does not wait for JavaScript.`,
212
+ });
213
+ }
214
+ if (css.willChangeElements.length > 0) {
215
+ issues.push({
216
+ severity: "info",
217
+ message: `will-change is set on ${css.willChangeElements.length} element(s). Remove it from elements that do not animate, since each one keeps a compositor layer.`,
218
+ });
219
+ }
220
+ return { items: items.slice(0, 50), issues };
221
+ };
222
+
191
223
  // ─── 4. SUMMARY ─────────────────────────────────────────────────────────────
192
224
 
193
225
  window.getScrollSummary = () => {
@@ -306,6 +338,7 @@
306
338
  console.groupEnd();
307
339
 
308
340
  const cssAuditResult = auditScrollCSS();
341
+ const findings = buildFindings(cssAuditResult);
309
342
  return {
310
343
  script: "Scroll-Performance",
311
344
  status: "ok",
@@ -315,6 +348,7 @@
315
348
  smoothScrollElements: cssAuditResult.smoothScrollElements.length,
316
349
  willChangeElements: cssAuditResult.willChangeElements.length,
317
350
  contentVisibilityElements: cssAuditResult.contentVisibilityElements.length,
351
+ overscrollElements: cssAuditResult.overscrollElements.length,
318
352
  },
319
353
  sessionCount: sessions.length,
320
354
  ...(sessions.length > 0 ? {
@@ -323,6 +357,8 @@
323
357
  totalDrops: sessions.reduce((a, s) => a + s.drops, 0),
324
358
  } : {}),
325
359
  },
360
+ items: findings.items,
361
+ issues: findings.issues,
326
362
  };
327
363
  };
328
364
 
@@ -342,6 +378,7 @@
342
378
  );
343
379
 
344
380
  const cssSnapshot = auditScrollCSS();
381
+ const initialFindings = buildFindings(cssSnapshot);
345
382
  return {
346
383
  script: "Scroll-Performance",
347
384
  status: "tracking",
@@ -351,8 +388,11 @@
351
388
  smoothScrollElements: cssSnapshot.smoothScrollElements.length,
352
389
  willChangeElements: cssSnapshot.willChangeElements.length,
353
390
  contentVisibilityElements: cssSnapshot.contentVisibilityElements.length,
391
+ overscrollElements: cssSnapshot.overscrollElements.length,
354
392
  },
355
393
  },
394
+ items: initialFindings.items,
395
+ issues: initialFindings.issues,
356
396
  message: "Scroll performance tracking active. Scroll the page then call getScrollSummary() for FPS data.",
357
397
  getDataFn: "getScrollSummary",
358
398
  };
@@ -58,6 +58,7 @@ When animations feel sluggish or the user asks "debug animation performance":
58
58
  2. **Long-Animation-Frames-Helpers.js** - Detailed frame timing analysis
59
59
  3. **Long-Animation-Frames-Script-Attribution.js** - Find scripts delaying frames
60
60
  4. **Scroll-Performance.js** - If scroll animations are involved
61
+ 5. **DOM-Size-and-Depth.js** - Check whether a large or deep DOM makes each style and layout pass expensive
61
62
 
62
63
  ### Third-Party Script Impact on Interactions
63
64
 
@@ -117,6 +118,7 @@ Use this decision tree to automatically run follow-up snippets based on results:
117
118
  - Debouncing/throttling event handlers
118
119
  - Web Workers for heavy computation
119
120
  - **If forced reflow/layout detected** → Analyze DOM manipulation patterns
121
+ - **If time goes to style recalculation or layout** → Run **DOM-Size-and-Depth.js** to check the size of the tree
120
122
 
121
123
  ### After LongTask.js
122
124
 
@@ -130,6 +132,13 @@ Use this decision tree to automatically run follow-up snippets based on results:
130
132
  - Excessive DOM manipulation
131
133
  - **If long tasks correlate with interactions** → Run **Interactions.js** to see impact
132
134
 
135
+ ### After DOM-Size-and-Depth.js
136
+
137
+ - **If total elements > 1400** → Recommend virtualizing long lists and loading off-screen content on demand
138
+ - **If depth > 32** → Recommend flattening wrapper elements added by components
139
+ - **If a single parent has > 60 children** → Recommend pagination or virtualization for that container
140
+ - **If the DOM is within limits but interactions are still slow** → Run **Long-Animation-Frames-Script-Attribution.js** to find the scripts responsible
141
+
133
142
  ### After Scroll-Performance.js
134
143
 
135
144
  - **If scroll FPS < 30** → Severe jank, run: