web-perf · diff

git:20260805.87b9536 to git:20260822.a6cb86f

71 added, 177 removed. Audit A to A.

---
name: web-perf
- description: Analyzes web performance using Chrome DevTools MCP. Measures Core Web Vitals (LCP, INP, CLS) and supplementary metrics (FCP, TBT, Speed Index), identifies render-blocking resources, network dependency chains, layout shifts, caching issues, and accessibility gaps. Use when asked to audit, profile, debug, or optimize page load performance, Lighthouse scores, or site speed. Biases towards retrieval from current documentation over pre-trained knowledge.
+ description: Measure, diagnose, or review web page performance when page speed, Core Web Vitals, Lighthouse performance, loading behavior, or a named performance regression is the primary task. Use current browser evidence and first-party documentation. Do not turn a focused metric investigation into a full performance, accessibility, bundler, and codebase audit.
---
- # Web Performance Audit
-
- Your knowledge of web performance metrics, thresholds, and tooling APIs may be outdated. **Prefer retrieval over pre-training** when citing specific numbers or recommendations.
-
- ## Retrieval Sources
-
- | Source | How to retrieve | Use for |
- |--------|----------------|---------|
- | web.dev | `https://web.dev/articles/vitals` | Core Web Vitals thresholds, definitions |
- | Chrome DevTools docs | `https://developer.chrome.com/docs/devtools/performance` | Tooling APIs, trace analysis |
- | Lighthouse scoring | `https://developer.chrome.com/docs/lighthouse/performance/performance-scoring` | Score weights, metric thresholds |
-
- ## FIRST: Verify MCP Tools Available
-
- **Run this before starting.** Try calling `navigate_page` or `performance_start_trace`. If unavailable, STOP—the chrome-devtools MCP server isn't configured.
-
- Ask the user to add this to their MCP config:
-
- ```json
- "chrome-devtools": {
- "type": "local",
- "command": ["npx", "-y", "chrome-devtools-mcp@latest"]
- }
- ```
-
- ## Key Guidelines
-
- - **Be assertive**: Verify claims by checking network requests, DOM, or codebase—then state findings definitively.
- - **Verify before recommending**: Confirm something is unused before suggesting removal.
- - **Quantify impact**: Use estimated savings from insights. Don't prioritize changes with 0ms impact.
- - **Skip non-issues**: If render-blocking resources have 0ms estimated impact, note but don't recommend action.
- - **Be specific**: Say "compress hero.png (450KB) to WebP" not "optimize images".
- - **Prioritize ruthlessly**: A site with 200ms LCP and 0 CLS is already excellent—say so.
-
- ## Quick Reference
-
- | Task | Tool Call |
- |------|-----------|
- | Load page | `navigate_page(url: "...")` |
- | Start trace | `performance_start_trace(autoStop: true, reload: true)` |
- | Analyze insight | `performance_analyze_insight(insightSetId: "...", insightName: "...")` |
- | List requests | `list_network_requests(resourceTypes: ["Script", "Stylesheet", ...])` |
- | Request details | `get_network_request(reqid: <id>)` |
- | A11y snapshot | `take_snapshot(verbose: true)` |
-
- ## Workflow
-
- Copy this checklist to track progress:
-
- ```
- Audit Progress:
- - [ ] Phase 1: Performance trace (navigate + record)
- - [ ] Phase 2: Core Web Vitals analysis (includes CLS culprits)
- - [ ] Phase 3: Network analysis
- - [ ] Phase 4: Accessibility snapshot
- - [ ] Phase 5: Codebase analysis (skip if third-party site)
- ```
-
- ### Phase 1: Performance Trace
-
- 1. Navigate to the target URL:
- ```
- navigate_page(url: "<target-url>")
- ```
-
- 2. Start a performance trace with reload to capture cold-load metrics:
- ```
- performance_start_trace(autoStop: true, reload: true)
- ```
-
- 3. Wait for trace completion, then retrieve results.
-
- **Troubleshooting:**
- - If trace returns empty or fails, verify the page loaded correctly with `navigate_page` first
- - If insight names don't match, inspect the trace response to list available insights
-
- ### Phase 2: Core Web Vitals Analysis
-
- Use `performance_analyze_insight` to extract key metrics.
-
- **Note:** Insight names may vary across Chrome DevTools versions. If an insight name doesn't work, check the `insightSetId` from the trace response to discover available insights.
-
- Common insight names:
-
- | Metric | Insight Name | What to Look For |
- |--------|--------------|------------------|
- | LCP | `LCPBreakdown` | Time to largest contentful paint; breakdown of TTFB, resource load, render delay |
- | CLS | `CLSCulprits` | Elements causing layout shifts (images without dimensions, injected content, font swaps) |
- | Render Blocking | `RenderBlocking` | CSS/JS blocking first paint |
- | Document Latency | `DocumentLatency` | Server response time issues |
- | Network Dependencies | `NetworkRequestsDepGraph` | Request chains delaying critical resources |
-
- Example:
- ```
- performance_analyze_insight(insightSetId: "<id-from-trace>", insightName: "LCPBreakdown")
- ```
-
- **Key thresholds (good/needs-improvement/poor):**
- - TTFB: < 800ms / < 1.8s / > 1.8s
- - FCP: < 1.8s / < 3s / > 3s
- - LCP: < 2.5s / < 4s / > 4s
- - INP: < 200ms / < 500ms / > 500ms
- - TBT: < 200ms / < 600ms / > 600ms
- - CLS: < 0.1 / < 0.25 / > 0.25
- - Speed Index: < 3.4s / < 5.8s / > 5.8s
-
- ### Phase 3: Network Analysis
-
- List all network requests to identify optimization opportunities:
- ```
- list_network_requests(resourceTypes: ["Script", "Stylesheet", "Document", "Font", "Image"])
- ```
-
- **Look for:**
-
- 1. **Render-blocking resources**: JS/CSS in `<head>` without `async`/`defer`/`media` attributes
- 2. **Network chains**: Resources discovered late because they depend on other resources loading first (e.g., CSS imports, JS-loaded fonts)
- 3. **Missing preloads**: Critical resources (fonts, hero images, key scripts) not preloaded
- 4. **Caching issues**: Missing or weak `Cache-Control`, `ETag`, or `Last-Modified` headers
- 5. **Large payloads**: Uncompressed or oversized JS/CSS bundles
- 6. **Unused preconnects**: If flagged, verify by checking if ANY requests went to that origin. If zero requests, it's definitively unused—recommend removal. If requests exist but loaded late, the preconnect may still be valuable.
-
- For detailed request info:
- ```
- get_network_request(reqid: <id>)
- ```
-
- ### Phase 4: Accessibility Snapshot
+ # Web Performance
- Take an accessibility tree snapshot:
- ```
- take_snapshot(verbose: true)
- ```
+ Use current browser evidence for the page and state the user named. Metrics,
+ thresholds, and tooling change; retrieve current web.dev or Chrome documentation
+ before citing specific thresholds or API details.
- **Flag high-level gaps:**
- - Missing or duplicate ARIA IDs
- - Elements with poor contrast ratios (check against WCAG AA: 4.5:1 for normal text, 3:1 for large text)
- - Focus traps or missing focus indicators
- - Interactive elements without accessible names
+ ## Set the acceptance scope
- ## Phase 5: Codebase Analysis
+ Choose the smallest mode that answers the request:
- **Skip if auditing a third-party site without codebase access.**
+ - **Named regression or metric:** measure that path and analyze its likely
+ contributors.
+ - **General performance audit:** capture representative load evidence, rank the
+ material issues, and stop when the highest-impact causes are explained.
+ - **Optimization work:** establish a comparable baseline, change only the
+ authorized code, and remeasure the same page, viewport, network conditions,
+ and cache state.
- Analyze the codebase to understand where improvements can be made.
+ The user outcome and performance risk created by the proposed change define the
+ gates. Accessibility, generic code quality, every bundler setting, and every
+ available DevTools insight are separate concerns unless the request or evidence
+ makes one relevant. A discovered non-blocking improvement is a follow-up, not a
+ release prerequisite.
- ### Detect Framework & Bundler
+ ## Choose available evidence
- Search for configuration files to identify the stack:
+ Prefer a browser tool that can record a performance trace and inspect network
+ requests. If the preferred Chrome DevTools integration is unavailable, use
+ another available browser measurement path or report the limitation. Do not
+ make installing a particular MCP server an acceptance gate unless the user asks
+ for that tool specifically.
- | Tool | Config Files |
- |------|--------------|
- | Webpack | `webpack.config.js`, `webpack.*.js` |
- | Vite | `vite.config.js`, `vite.config.ts` |
- | Rollup | `rollup.config.js`, `rollup.config.mjs` |
- | esbuild | `esbuild.config.js`, build scripts with `esbuild` |
- | Parcel | `.parcelrc`, `package.json` (parcel field) |
- | Next.js | `next.config.js`, `next.config.mjs` |
- | Nuxt | `nuxt.config.js`, `nuxt.config.ts` |
- | SvelteKit | `svelte.config.js` |
- | Astro | `astro.config.mjs` |
+ Useful evidence, selected as needed:
- Also check `package.json` for framework dependencies and build scripts.
+ - a cold or warm page-load trace;
+ - Core Web Vitals and the element or interaction that owns the metric;
+ - the critical network dependency chain and response headers;
+ - request payload sizes and estimated savings;
+ - relevant DOM or source ownership for the measured culprit;
+ - field data when the user asks about real-user performance and it is available.
- ### Tree-Shaking & Dead Code
+ Keep lab and field evidence distinct. Record the URL, viewport, cache state,
+ network/CPU conditions, and run count when they materially affect comparison.
- - **Webpack**: Check for `mode: 'production'`, `sideEffects` in package.json, `usedExports` optimization
- - **Vite/Rollup**: Tree-shaking enabled by default; check for `treeshake` options
- - **Look for**: Barrel files (`index.js` re-exports), large utility libraries imported wholesale (lodash, moment)
+ ## Focused workflow
- ### Unused JS/CSS
+ 1. Reproduce the named page, route, viewport, and state.
+ 2. Capture a trace or the narrowest available measurement. Repeat only enough
+ to distinguish a stable signal from obvious noise.
+ 3. Inspect the insight, requests, DOM, or code that can confirm the leading
+ cause. Do not infer an unused or blocking resource from naming alone.
+ 4. Rank only issues with material measured or well-supported impact. A 0 ms
+ estimate or already-good metric is not an optimization task.
+ 5. If implementation is requested, make the smallest relevant change and
+ remeasure under comparable conditions.
+ 6. Stop when the requested metric or regression is explained, or the authorized
+ change is comparably verified. State uncertainty and follow-ups separately.
- - Check for CSS-in-JS vs. static CSS extraction
- - Look for PurgeCSS/UnCSS configuration (Tailwind's `content` config)
- - Identify dynamic imports vs. eager loading
+ ## Risk-triggered checks
- ### Polyfills
+ Select these only when the evidence points to them:
- - Check for `@babel/preset-env` targets and `useBuiltIns` setting
- - Look for `core-js` imports (often oversized)
- - Check `browserslist` config for overly broad targeting
+ - **LCP or FCP:** server latency, resource discovery, render delay, hero/font
+ priority, and render-blocking resources.
+ - **CLS:** the actual shifting elements, missing dimensions, injected content,
+ and font behavior.
+ - **INP or main-thread delay:** the measured interaction, long tasks, event
+ handlers, hydration, and script evaluation.
+ - **Network weight or dependency depth:** compression, caching, payload size,
+ request chains, preloads, and preconnect usage.
+ - **Bundle ownership:** framework and bundler configuration only far enough to
+ locate the measured cost; do not run a generic tree-shaking audit by default.
- ### Compression & Minification
+ Verify before recommending removal. Confirm request use, execution, or coverage
+ with current evidence, and avoid prescribing framework-specific configuration
+ from memory.
- - Check for `terser`, `esbuild`, or `swc` minification
- - Look for gzip/brotli compression in build output or server config
- - Check for source maps in production builds (should be external or disabled)
+ ## Report
- ## Output Format
+ Lead with the answer to the performance question. Include:
- Present findings as:
+ - measured values and conditions;
+ - the highest-impact confirmed causes;
+ - specific fixes or completed changes with expected or measured impact;
+ - evidence unavailable or too noisy to support a claim; and
+ - non-blocking opportunities as follow-ups.
- 1. **Core Web Vitals Summary** - Table with metric, value, and rating (good/needs-improvement/poor)
- 2. **Top Issues** - Prioritized list of problems with estimated impact (high/medium/low)
- 3. **Recommendations** - Specific, actionable fixes with code snippets or config changes
- 4. **Codebase Findings** - Framework/bundler detected, optimization opportunities (omit if no codebase access)
+ Use a metric table only when multiple measurements benefit from comparison. Do
+ not claim a full audit when only one trace, page, viewport, or lab environment
+ was tested.