技能 硬件工程 PageSpeed/Lighthouse性能审计增强

PageSpeed/Lighthouse性能审计增强

v20260614
pagespeed-enhancer
这是一个结构化的工作流,用于全面审计和优化网站性能。它覆盖Lighthouse的四大支柱(性能、可访问性、最佳实践和SEO),系统分析核心网页指标(如LCP, CLS)、渲染阻塞资源、安全头部和ARIA合规性,提供可执行的修复方案。
获取技能
275 次下载
概览

PageSpeed Enhancer Skill

A structured, batch-wise audit-and-fix workflow for all four Lighthouse pillars. Always follow the batch flow in order. Never jump straight to fixes without completing the scan and risk assessment phases.


When to Use This Skill

  • User pastes a PageSpeed Insights report or mentions Lighthouse scores
  • User asks to improve Core Web Vitals (LCP, FCP, CLS, TBT, SI)
  • User needs help with render-blocking resources, unused JavaScript, image optimisation, security headers, ARIA compliance, or SEO meta-tag fixes
  • User asks "why is my LCP slow", "fix accessibility issues", "improve my SEO score", or "my site scores 80 on performance"
  • Any mention of PageSpeed, Lighthouse, Web Vitals, or site speed

High-Level Workflow

PHASE 1 → Ingest Report & Parse Scores
PHASE 2 → Batch Scan (4 sections, parallel analysis)
PHASE 3 → Consolidated Risk Report (changes ranked by impact vs risk)
PHASE 4 → Fix Batches (applied in safe order: low-risk → high-risk)
PHASE 5 → Verification Checklist

PHASE 1 — Ingest & Classify

When the user provides a PageSpeed Insights report (pasted text, screenshot, or URL):

  1. Extract the four pillar scores: Performance, Accessibility, Best Practices, SEO.
  2. Extract each flagged metric with its value and Lighthouse weight.
  3. Identify the critical path bottleneck (the single issue most responsible for the lowest pillar score).
  4. Output a Score Summary Table:
| Pillar          | Score | Status  | Critical Issue                      |
|-----------------|-------|---------|-------------------------------------|
| Performance     | 80    | ⚠️ Warn | LCP 4.0s — element render delay     |
| Accessibility   | 100   | ✅ Pass | —                                   |
| Best Practices  | 100   | ✅ Pass | CSP missing (unscored)              |
| SEO             | 100   | ✅ Pass | —                                   |

Then proceed immediately to Phase 2 without waiting for user input unless the report is ambiguous.


PHASE 2 — Batch Scan (4 Sections)

Run all four section scans. Present as collapsible sections in output.

Batch A — Performance Scan

Audit these in order (highest Lighthouse weight first):

Audit Metric Impact Key Questions
LCP breakdown LCP Is the LCP element lazily loaded? Is TTFB > 600ms? Is element render delay > 1s?
Render-blocking resources FCP, LCP Which CSS/JS files block the critical path? Can they be deferred or inlined?
CSS @import rules FCP, LCP Are external stylesheets loaded via @import url() in CSS? This is 2x render-blocking — browser must fetch CSS, parse it, then fetch imported CSS. Use <link> instead.
Unused JavaScript FCP, LCP, TBT What % of the main bundle is unused? Is code-splitting possible?
Network dependency tree LCP What is the critical path chain? Max latency?
Forced reflows TBT Which JS functions query geometry after DOM mutation?
Image delivery FCP, LCP Are images in WebP/AVIF? Are above-fold images lazy-loaded?
Speed Index SI Is page visually progressive or does it paint all at once?
CLS culprits CLS Any images without width/height? Any late-injected content?
JavaScript execution time TBT Total parse + compile + evaluate time?
Long main-thread tasks TBT Tasks > 50ms? Starting when?
Bundled asset sizes FCP, LCP, TBT Check dist/ output: any single JS chunk > 500KB gzipped? CSS > 100KB? Code-splitting creating proper vendor chunks?

For each audit item, output:

  • Finding: What the report says
  • Root Cause: Why it's happening
  • Fix Category: Quick Win / Medium Effort / Refactor Required

Batch B — Accessibility Scan

Focus on any failed audits. For a 100-score page, still check:

Check What to Verify
ARIA attribute correctness All aria-* attributes match element roles
Colour contrast All text meets WCAG AA (4.5:1 normal, 3:1 large)
Image alt text quality Alt text is descriptive, not filename-style
Keyboard navigation All interactive elements reachable by Tab
Skip links Present and focusable
Heading hierarchy No skipped levels (h1 → h2 → h3)
Touch target size Min 44×44px on mobile
Form labels Every input has an associated label
lang attribute <html lang="en"> present and valid BCP 47
font-display Set to swap or optional to prevent FOIT

Batch C — Best Practices Scan

Security headers are often unflagged by Lighthouse score but are critical. Check ALL deployment targets:

Check Header/Setting Where to Configure Severity
Content Security Policy Content-Security-Policy netlify.toml [[headers]] / vercel.json "headers" 🔴 High
Cross-Origin-Opener-Policy COOP header Same as above 🔴 High
Clickjacking protection X-Frame-Options or CSP frame-ancestors Same as above 🔴 High
HSTS configuration Strict-Transport-Security with includeSubDomains + preload Same as above 🟡 Medium
Trusted Types (DOM XSS) CSP require-trusted-types-for 'script' Same as above 🟡 Medium
X-Content-Type-Options nosniff header Same as above 🟡 Medium
Referrer-Policy strict-origin-when-cross-origin Same as above 🟡 Medium
Permissions-Policy Restrict camera/mic/geolocation Same as above 🟡 Medium
Third-party cookies Any SameSite=None cookies without Secure? 🟡 Medium
Deprecated APIs Any browser-deprecated JS APIs in use? 🟢 Low
Source maps Are source maps deployed for debugging? 🟢 Low

When both netlify.toml and vercel.json exist, check BOTH. Each has a different syntax (TOML vs JSON).

Batch D — SEO Scan

Check What to Verify
<title> tag Present, 50–60 chars, includes primary keyword
Meta description Present, 150–160 chars, compelling
Canonical tag <link rel="canonical"> points to correct URL
hreflang Present if multilingual; correct language codes
robots.txt Valid, not blocking key resources
Structured data JSON-LD present; run Schema validator
Image alt attributes Every <img> has meaningful alt
Link descriptiveness No "click here" / "read more" link text
Crawlability No noindex on important pages
HTTP status 200 on main page and critical resources
SPA meta injection If using react-helmet-async / Next.js Head: verify via "View Page Source", not DevTools Elements — meta tags may be JS-injected

PHASE 3 — Risk Report

After completing all four batch scans, output a consolidated Risk vs Impact Matrix:

| Fix                              | Impact Score | Risk Level | Effort   | Priority |
|----------------------------------|-------------|------------|----------|----------|
| Add defer/async to non-critical JS | High (LCP -0.8s est) | 🟢 Low | 1h     | P1       |
| Convert images to WebP/AVIF      | Medium (LCP -0.3s)   | 🟢 Low | 2h     | P1       |
| Add CSP header                   | Security    | 🟡 Medium  | 3h     | P2       |
| Code-split main JS bundle        | High (TBT -20ms)     | 🟡 Medium | 1 day | P2       |
| Fix forced reflows               | Medium (TBT -15ms)   | 🔴 High   | 2 days | P3       |
| Add HSTS preload                 | Security    | 🟡 Medium  | 30min  | P2       |

Risk Level Definitions:

  • 🟢 Low: Config/header change, no code change. Rollback in < 5 min.
  • 🟡 Medium: Build config or asset pipeline change. Test in staging first.
  • 🔴 High: JavaScript refactor, architectural change. Requires full QA cycle.

Always recommend: fix P1 (Low Risk, High Impact) items first, then P2, then P3.


PHASE 4 — Fix Batches

Apply fixes in risk order. For each fix, provide:

  1. What to change — file, line, specific change
  2. Before (code snippet)
  3. After (code snippet)
  4. Expected metric improvement — estimated delta
  5. How to verify — what to check after deploying

Fix Batch 1 — Quick Wins (Low Risk, deploy immediately)

Examples from common audits:

F1.1 — Move CSS @import to <link> tag

CSS @import url() is 2x render-blocking. Move to <link> in <head>:

/* Before: in index.css */
@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');
<!-- After: in index.html <head> -->
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&display=swap" media="print" onload="this.media='all'" />
<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&display=swap" /></noscript>

F1.2 — Defer render-blocking CSS (if not above-fold critical)

<!-- Before -->
<link rel="stylesheet" href="/assets/index.css">

<!-- After: load async, apply on load -->
<link rel="preload" href="/assets/index.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/assets/index.css"></noscript>

F1.3 — Fix broken preconnect (crossorigin mismatch)

<!-- Before (broken — no crossorigin on font CDN) -->
<link rel="preconnect" href="https://api.rss2json.com">

<!-- After -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Only preconnect origins used in critical path, max 4 -->

F1.4 — Convert images to WebP

# Using cwebp
cwebp -q 80 input.jpeg -o output.webp

# Using sharp (Node.js)
sharp('image.jpeg').webp({ quality: 80 }).toFile('image.webp')

# macOS fallback (sips built-in)
sips -s format webp input.jpeg --out output.webp

# Python Pillow fallback
python3 -c "
from PIL import Image
Image.open('input.jpg').save('output.webp', 'WebP', quality=80)
"

F1.5 — Add explicit image dimensions (CLS fix)

<!-- Before -->
<img src="hero.webp" alt="...">

<!-- After -->
<img src="hero.webp" alt="..." width="800" height="400">

F1.6 — Add security headers (netlify.toml)

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
    Cross-Origin-Opener-Policy = "same-origin"
    Permissions-Policy = "camera=(), microphone=(), geolocation=()"
    Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self' https://api.rss2json.com"

F1.7 — Add security headers (vercel.json)

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains; preload" },
        { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
        { "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self' https://api.rss2json.com" }
      ]
    }
  ]
}

F1.8 — Self-host Google Fonts (eliminate external CSS request)

Download woff2 files and serve them locally to remove the Google Fonts CSS round-trip entirely:

# 1. Download woff2 files from Google Fonts CSS URL
#    Open https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap
#    in a browser, then download each woff2 URL listed in the @font-face blocks.

# 2. Place files in public/fonts/ or src/assets/fonts/
public/fonts/
  inter-v12-latin-400.woff2
  inter-v12-latin-700.woff2

# 3. Add @font-face CSS (load once, no external request)
/* src/styles/fonts.css */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-v12-latin-400.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/inter-v12-latin-700.woff2') format('woff2');
}
/* Remove the old Google Fonts <link> from index.html */
/* Before: */
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">

/* After: just use the font-family normally */
body { font-family: 'Inter', sans-serif; }

Result: Zero external CSS requests, faster FCP/LCP, no FOIT risk, and works offline.

F1.9 — Resize oversized icons

Icons (favicon, apple-touch-icon, OG image) should never be > 50KB. Check and resize:

python3 -c "
from PIL import Image
img = Image.open('favicon.png')
img.resize((192, 192)).save('favicon.png', 'PNG', optimize=True)
img.resize((32, 32)).save('favicon-32x32.png', 'PNG', optimize=True)
img.resize((16, 16)).save('favicon-16x16.png', 'PNG', optimize=True)
"

Fix Batch 2 — Medium Effort (staging test recommended)

F2.1 — Remove LCP element lazy loading

The LCP element must NEVER be lazy-loaded:

<!-- Before: wrong — LCP image is lazy -->
<img src="hero.webp" loading="lazy" ...>

<!-- After: eager load the above-fold LCP element -->
<img src="hero.webp" loading="eager" fetchpriority="high" ...>

F2.2 — Preload LCP image

⚠️ Only works for files in public/ or with stable URLs. If using Vite/Webpack (content-hashed filenames), use <picture> + fetchPriority="high" instead:

<!-- For stable URLs (public/ directory): -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">

<!-- For hashed filenames (Vite/Rollup): use component-level approach -->
<picture>
  <source srcSet={webpImage} type="image/webp" />
  <img src={jpgImage} fetchPriority="high" loading="eager" width="1920" height="1080" />
</picture>

F2.3 — Reduce unused JS (Vite/Rollup config)

// vite.config.js — enable manual chunking
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        vendor: ['react', 'react-dom'],
        rss: ['rss-parser'],
      }
    }
  }
}

F2.4 — Eliminate forced reflows

// Before: reads layout property inside animation loop
element.addEventListener('scroll', () => {
  const h = element.offsetHeight; // triggers reflow
  doSomething(h);
});

// After: cache geometry reads outside event handlers
const h = element.offsetHeight; // read once
element.addEventListener('scroll', () => {
  doSomething(h);
});

F2.5 — Optimise DOM size

If DOM > 1,500 elements:

  • Use virtual scrolling for long lists (react-virtual, TanStack Virtual)
  • Lazy-render off-screen sections
  • Remove hidden/display:none nodes that never become visible

Fix Batch 3 — Refactor Required (full QA cycle)

F3.1 — External API in critical path (e.g. api.rss2json.com)

Current: HTML → JS bundle → external API (adds 1,574ms to critical path)

Solution: Move external API calls to build time or server-side:

// Option A: Fetch at build time (Astro/Next.js SSG)
export async function getStaticProps() {
  const res = await fetch('https://api.rss2json.com/v1/api.json?rss_url=...');
  const data = await res.json();
  return { props: { posts: data.items }, revalidate: 3600 };
}

// Option B: Edge function / serverless proxy
// Cache RSS response at CDN edge, return stale-while-revalidate

F3.2 — Content Security Policy (full CSP)

Build the CSP iteratively:

  1. Deploy in report-only mode first: Content-Security-Policy-Report-Only
  2. Check browser console for violations for 48h
  3. Whitelist required origins
  4. Promote to enforcement mode

PRE-DEPLOY GATE

Before deploying any fix batch, run these checks:

Build:
□ npm run build (or equivalent) — exits 0
□ npm run lint / typecheck — no new errors vs baseline
□ Inspect dist/ output:
   - No single JS chunk > 500KB (gzipped)
   - CSS < 100KB
   - Code-splitting created separate vendor chunks

Asset verification:
□ For Vite/Rollup/Webpack: preload <link> in index.html won't match hashed filenames.
  Use fetchPriority="high" + <picture> on the component instead.
□ Favicons and icons are < 50KB each (not multi-MB source images used as icons)
□ WebP/AVIF versions exist alongside originals

Deploy target:
□ If dual-deployed (Netlify + Vercel), verify headers on BOTH
□ If using SPA framework: verify meta tags via "View Page Source", not DevTools Elements
  (react-helmet-async injects at runtime — check prerendered/SSR output)

PHASE 5 — Verification Checklist

After deploying each fix batch, verify:

Performance:
□ Re-run PageSpeed Insights on mobile AND desktop
□ LCP < 2.5s (Good)
□ FCP < 1.8s (Good)
□ TBT < 200ms (Good)
□ CLS < 0.1 (Good)
□ SI < 3.4s (Good)

Accessibility:
□ Run axe DevTools browser extension
□ Navigate page with keyboard only (Tab, Shift+Tab, Enter, Space)
□ Test with screen reader (NVDA/VoiceOver)
□ Check contrast with browser DevTools accessibility panel

Best Practices:
□ Verify security headers at https://securityheaders.com
□ Check HTTPS: no mixed content warnings in DevTools
□ Run Lighthouse Best Practices audit again

SEO:
□ Validate structured data at https://search.google.com/test/rich-results
□ Check robots.txt at /robots.txt
□ Verify canonical tag in page source (View Source, not DevTools)
□ Submit updated sitemap to Google Search Console

Output Format Conventions

  • Always label outputs: [SCAN], [RISK], [FIX], [VERIFY]
  • Use emoji severity indicators: 🔴 Critical / 🟡 Warning / 🟢 Pass / ℹ️ Info
  • Always show "Before" and "After" code for every fix
  • Always include estimated metric delta (e.g. "Est. LCP improvement: -0.8s")
  • Never suggest fixes that conflict with each other — sequence matters

Quick Reference: Metric Thresholds

Metric Good Needs Work Poor
FCP < 1.8s 1.8–3.0s > 3.0s
LCP < 2.5s 2.5–4.0s > 4.0s
TBT < 200ms 200–600ms > 600ms
CLS < 0.1 0.1–0.25 > 0.25
SI < 3.4s 3.4–5.8s > 5.8s

Examples

Example 1: User pastes a PageSpeed report

User: "My site scores 65 on Performance. LCP is 4.2s."

Agent:

  1. Parses the score summary table — identifies LCP as critical bottleneck
  2. Runs Batch A scan — finds lazy-loaded hero image and render-blocking CSS
  3. Outputs risk report: F1.1 (CSS @import → link) ranked P1, F1.5 (LCP image eager) ranked P1
  4. Applies Fix Batch 1, verifies with re-test

Example 2: User asks about slow LCP

User: "Why is my LCP slow?"

Agent:

  1. Asks for a PageSpeed report URL or pasted results
  2. Runs LCP-specific audit from Batch A — checks TTFB, element render delay, lazy loading
  3. Identifies the LCP element, its current loading strategy, and the critical path chain
  4. Recommends targeted fix (preload, eager loading, or server response time improvement)

Limitations

  • Does not run actual Lighthouse or PageSpeed tests — the user must provide the report or URL
  • Security header recommendations assume the user controls the deployment platform (Netlify, Vercel, etc.)
  • Fixes are general patterns; exact file paths and config syntax may vary by project setup
  • Does not cover server-level optimisations (CDN config, PHP opcode caching, database queries, etc.)
  • Image conversion commands assume the user has the required tools installed (cwebp, sharp, Pillow)
  • CSP guidance uses a report-only iterative approach — the final policy must be tuned to each project's actual resource origins

Change Log & Revert Checklist

After each fix batch, log what changed and whether it caused build failures:

Fix File(s) Modified Build Pass? Errors Revert Steps
F1.1 — CSS @import → <link> index.html, src/styles/*.css □ Yes □ No Restore original <link> tags
F1.2 — Defer render-blocking CSS index.html □ Yes □ No Remove media="print" + onload
F1.4 — WebP conversion public/images/*.webp □ Yes □ No Delete .webp files, restore originals
F1.5 — Image dimensions src/components/*.tsx □ Yes □ No Remove width/height/loading attrs
F1.6 — Security headers (Netlify) netlify.toml □ Yes □ No Delete the [[headers]] block
F1.7 — Security headers (Vercel) vercel.json □ Yes □ No Remove the "headers" array entry
F1.8 — Self-host fonts public/fonts/*.woff2, src/styles/fonts.css, index.html □ Yes □ No Delete font files, remove @font-face, restore Google Fonts <link>
F1.9 — Resize icons public/favicon*, public/apple-touch-icon*, public/og-image* □ Yes □ No Restore original icon files
F2.1 — LCP eager loading src/components/*.tsx □ Yes □ No Change loading="eager" back to loading="lazy"
F2.2 — Preload LCP image index.html or src/components/*.tsx □ Yes □ No Remove <link rel="preload"> or revert <picture>
F2.3 — Code-split JS vite.config.ts □ Yes □ No Remove manualChunks config
F2.4 — Fix forced reflows src/**/*.ts □ Yes □ No Revert geometry caching changes
F2.5 — Optimise DOM src/components/*.tsx □ Yes □ No Restore removed hidden nodes
F3.1 — External API to build time src/**/*.ts, config files □ Yes □ No Restore client-side fetch
F3.2 — CSP headers netlify.toml / vercel.json □ Yes □ No Remove or relax CSP directives

If Build Pass? is No, run npm run build to see the exact error, revert the failed fix immediately, and re-test before applying the next batch.


References

See references/ for deep-dives:

  • references/performance-deep-dive.md — LCP, CLS, TBT root cause trees
  • references/security-headers.md — Complete CSP/HSTS/COOP reference
  • references/image-optimization.md — WebP/AVIF conversion pipelines
信息
Category 硬件工程
Name pagespeed-enhancer
版本 v20260614
大小 22.55KB
更新时间 2026-06-15
语言