web-perf

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Web Performance Audit

Web性能审计

Structured 5-phase web performance audit workflow. Diagnose performance bottlenecks, measure Core Web Vitals, and produce actionable optimization recommendations.
结构化的5阶段Web性能审计工作流,可用于诊断性能瓶颈、测量Core Web Vitals以及输出可落地的优化建议。

When to Apply

适用场景

Use this skill when:
  • Auditing website performance for Core Web Vitals compliance
  • Diagnosing slow page loads, high Time to Interactive, or layout shifts
  • Optimizing Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS), or Interaction to Next Paint (INP)
  • Reviewing frontend code for performance anti-patterns
  • Preparing a site for Google's page experience ranking signals
  • Optimizing build output for Webpack, Vite, Next.js, or Nuxt
在以下场景中使用本技能:
  • 审计网站性能是否符合Core Web Vitals合规要求
  • 诊断页面加载缓慢、可交互时间过长、布局偏移等问题
  • 优化最大内容绘制(LCP)、累积布局偏移(CLS)或下一次绘制交互(INP)指标
  • 审查前端代码中的性能反模式
  • 为网站适配谷歌页面体验排名信号做准备
  • 优化Webpack、Vite、Next.js或Nuxt的构建产物

Core Web Vitals Thresholds

Core Web Vitals阈值

MetricGoodNeeds ImprovementPoorWhat It Measures
LCP<= 2.5s2.5s - 4.0s> 4.0sLoading performance
CLS<= 0.10.1 - 0.25> 0.25Visual stability
INP<= 200ms200ms - 500ms> 500msInteractivity (replaced FID)
指标优秀需要改进较差测量维度
LCP<= 2.5s2.5s - 4.0s> 4.0s加载性能
CLS<= 0.10.1 - 0.25> 0.25视觉稳定性
INP<= 200ms200ms - 500ms> 500ms交互性(已取代FID)

Additional Performance Metrics

额外性能指标

MetricGoodPoorWhat It Measures
FCP<= 1.8s> 3.0sFirst content rendered
TTFB<= 800ms> 1800msServer response time
TBT<= 200ms> 600msMain thread blocking
Speed Index<= 3.4s> 5.8sVisual completeness over time
指标优秀阈值较差阈值测量维度
首次内容绘制(FCP)<= 1.8s> 3.0s首个内容元素渲染完成时间
首字节时间(TTFB)<= 800ms> 1800ms服务器响应时间
总阻塞时间(TBT)<= 200ms> 600ms主线程阻塞总时长
速度指数<= 3.4s> 5.8s页面内容视觉加载完成速度

5-Phase Audit Workflow

5阶段审计工作流

Phase 1: Performance Trace

阶段1:性能追踪

Capture a performance trace to establish baseline metrics.
Browser-Based (Chrome DevTools):
  1. Open Chrome DevTools (F12) > Performance tab
  2. Click "Record" and reload the page
  3. Stop recording after page fully loads
  4. Analyze the flame chart for:
    • Long tasks (> 50ms, marked in red)
    • Layout thrashing (forced reflow cycles)
    • Render-blocking resources
    • JavaScript execution bottlenecks
Lighthouse Audit:
bash
undefined
采集性能追踪数据建立基准指标。
基于浏览器(Chrome DevTools):
  1. 打开Chrome DevTools(F12)> 性能面板
  2. 点击「录制」并重新加载页面
  3. 页面完全加载后停止录制
  4. 分析火焰图排查以下问题:
    • 长任务(> 50ms,标记为红色)
    • 布局抖动(强制重排循环)
    • 阻塞渲染的资源
    • JavaScript执行瓶颈
Lighthouse审计:
bash
undefined

CLI-based Lighthouse audit

CLI模式Lighthouse审计

npx lighthouse https://example.com --output=json --output-path=./lighthouse-report.json
npx lighthouse https://example.com --output=json --output-path=./lighthouse-report.json

With specific categories

指定审计类别

npx lighthouse https://example.com --only-categories=performance --output=html
npx lighthouse https://example.com --only-categories=performance --output=html

Mobile simulation (default)

移动端模拟(默认)

npx lighthouse https://example.com --preset=perf --throttling-method=simulate

**Key Trace Indicators:**

- **Main thread busy time**: Should be < 4s total
- **Largest task duration**: Should be < 250ms
- **Script evaluation time**: Should be < 2s
- **Layout/style recalculation**: Should be < 500ms
npx lighthouse https://example.com --preset=perf --throttling-method=simulate

**核心追踪指标:**

- **主线程忙碌总时长**:应< 4s
- **最大任务耗时**:应< 250ms
- **脚本执行时间**:应< 2s
- **布局/样式重计算耗时**:应< 500ms

Phase 2: Core Web Vitals Analysis

阶段2:Core Web Vitals分析

Measure each Core Web Vital and identify specific causes.
测量每一项Core Web Vitals指标并定位具体诱因。

LCP Diagnosis

LCP诊断

LCP measures loading performance -- when the largest content element becomes visible.
Common LCP Elements:
  • <img>
    elements (hero images)
  • <video>
    poster images
  • Block-level elements with background images
  • Text blocks (
    <h1>
    ,
    <p>
    )
LCP Optimization Checklist:
  1. Preload the LCP resource
    html
    <link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />
  2. Eliminate render-blocking resources
    html
    <!-- Defer non-critical CSS -->
    <link rel="stylesheet" href="/non-critical.css" media="print" onload="this.media='all'" />
    
    <!-- Async non-critical JS -->
    <script src="/analytics.js" async></script>
  3. Optimize server response time (TTFB)
    • Use CDN for static assets
    • Enable HTTP/2 or HTTP/3
    • Implement server-side caching
    • Use streaming SSR where supported
  4. Optimize image delivery
    html
    <!-- Modern format with fallback -->
    <picture>
      <source srcset="/hero.avif" type="image/avif" />
      <source srcset="/hero.webp" type="image/webp" />
      <img
        src="/hero.jpg"
        alt="Hero"
        width="1200"
        height="600"
        fetchpriority="high"
        decoding="async"
      />
    </picture>
LCP衡量加载性能——最大内容元素变为可见的时间。
常见LCP元素:
  • <img>
    元素(头图)
  • <video>
    封面图
  • 带背景图的块级元素
  • 文本块(
    <h1>
    <p>
LCP优化 Checklist:
  1. 预加载LCP资源
    html
    <link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />
  2. 移除阻塞渲染的资源
    html
    <!-- 延迟加载非关键CSS -->
    <link rel="stylesheet" href="/non-critical.css" media="print" onload="this.media='all'" />
    
    <!-- 异步加载非关键JS -->
    <script src="/analytics.js" async></script>
  3. 优化服务器响应时间(TTFB)
    • 静态资源使用CDN
    • 启用HTTP/2或HTTP/3
    • 实现服务端缓存
    • 支持的场景下使用流式SSR
  4. 优化图片分发
    html
    <!-- 现代格式加降级方案 -->
    <picture>
      <source srcset="/hero.avif" type="image/avif" />
      <source srcset="/hero.webp" type="image/webp" />
      <img
        src="/hero.jpg"
        alt="Hero"
        width="1200"
        height="600"
        fetchpriority="high"
        decoding="async"
      />
    </picture>

CLS Diagnosis

CLS诊断

CLS measures visual stability -- unexpected layout shifts during page load.
Common CLS Causes:
  • Images without explicit dimensions
  • Ads or embeds without reserved space
  • Dynamically injected content above the fold
  • Web fonts causing FOIT/FOUT (Flash of Invisible/Unstyled Text)
CLS Optimization Checklist:
  1. Always set image dimensions
    html
    <img src="/photo.jpg" width="800" height="600" alt="Photo" />
    Or use CSS aspect-ratio:
    css
    .hero-image {
      aspect-ratio: 16 / 9;
      width: 100%;
    }
  2. Reserve space for dynamic content
    css
    .ad-slot {
      min-height: 250px;
    }
    .skeleton {
      height: 200px;
      background: #f0f0f0;
    }
  3. Use
    font-display: swap
    with size-adjust
    css
    @font-face {
      font-family: 'CustomFont';
      src: url('/font.woff2') format('woff2');
      font-display: swap;
      size-adjust: 100.5%; /* Match fallback font metrics */
    }
  4. Avoid inserting content above existing content
    • Banners should push down from top, not shift existing content
    • Use
      transform
      animations instead of
      top
      /
      left
      /
      width
      /
      height
CLS衡量视觉稳定性——页面加载过程中意外布局偏移的程度。
常见CLS诱因:
  • 未明确设置尺寸的图片
  • 未预留占位空间的广告或嵌入内容
  • 首屏区域动态注入的内容
  • Web字体导致FOIT/FOUT(无样式文本闪烁/不可见文本闪烁)
CLS优化 Checklist:
  1. 始终设置图片尺寸
    html
    <img src="/photo.jpg" width="800" height="600" alt="Photo" />
    或使用CSS aspect-ratio:
    css
    .hero-image {
      aspect-ratio: 16 / 9;
      width: 100%;
    }
  2. 为动态内容预留占位空间
    css
    .ad-slot {
      min-height: 250px;
    }
    .skeleton {
      height: 200px;
      background: #f0f0f0;
    }
  3. 结合
    font-display: swap
    与size-adjust使用
    css
    @font-face {
      font-family: 'CustomFont';
      src: url('/font.woff2') format('woff2');
      font-display: swap;
      size-adjust: 100.5%; /* 匹配降级字体指标 */
    }
  4. 避免在已有内容上方插入新内容
    • 横幅应从顶部向下推开内容,而非挤压已有内容产生偏移
    • 动画使用
      transform
      而非
      top
      /
      left
      /
      width
      /
      height
      属性

INP Diagnosis

INP诊断

INP measures interactivity -- the delay between user interaction and visual response.
Common INP Causes:
  • Long JavaScript tasks blocking the main thread
  • Synchronous layout/style recalculations
  • Heavy event handlers
  • Excessive re-renders (React, Vue)
INP Optimization Checklist:
  1. Break up long tasks
    javascript
    // Instead of one long task
    function processAllItems(items) {
      for (const item of items) {
        /* heavy work */
      }
    }
    
    // Break into chunks with scheduler
    async function processAllItems(items) {
      for (const item of items) {
        processItem(item);
        // Yield to main thread between items
        await scheduler.yield();
      }
    }
  2. Debounce/throttle event handlers
    javascript
    // Throttle scroll handler
    let ticking = false;
    window.addEventListener(
      'scroll',
      () => {
        if (!ticking) {
          requestAnimationFrame(() => {
            updateUI();
            ticking = false;
          });
          ticking = true;
        }
      },
      { passive: true }
    );
  3. Use
    requestIdleCallback
    for non-urgent work
    javascript
    requestIdleCallback(() => {
      // Analytics, prefetching, non-visible updates
      sendAnalytics(data);
    });
INP衡量交互性——用户交互到页面视觉响应之间的延迟。
常见INP诱因:
  • 长JavaScript任务阻塞主线程
  • 同步布局/样式重计算
  • 过重的事件处理函数
  • 过度重渲染(React、Vue)
INP优化 Checklist:
  1. 拆分长任务
    javascript
    // 替换单长任务写法
    function processAllItems(items) {
      for (const item of items) {
        /* 重计算逻辑 */
      }
    }
    
    // 通过调度器拆分为多个小任务
    async function processAllItems(items) {
      for (const item of items) {
        processItem(item);
        // 处理单个条目后让渡主线程
        await scheduler.yield();
      }
    }
  2. 防抖/节流事件处理函数
    javascript
    // 节流滚动处理函数
    let ticking = false;
    window.addEventListener(
      'scroll',
      () => {
        if (!ticking) {
          requestAnimationFrame(() => {
            updateUI();
            ticking = false;
          });
          ticking = true;
        }
      },
      { passive: true }
    );
  3. 非紧急任务使用
    requestIdleCallback
    javascript
    requestIdleCallback(() => {
      // 埋点上报、预加载、非可见区域更新等逻辑
      sendAnalytics(data);
    });

Phase 3: Network Analysis

阶段3:网络分析

Analyze network waterfall for optimization opportunities.
Key Checks:
  1. Resource count and total size
    • Target: < 100 requests, < 2MB total (compressed)
    • Check:
      performance.getEntriesByType('resource').length
  2. Critical request chains
    • Identify chains longer than 3 requests
    • Break chains with preload/prefetch hints
  3. Compression
    • All text resources should use Brotli (br) or gzip
    • Check
      Content-Encoding
      header in response
  4. Caching headers
    # Immutable assets (hashed filenames)
    Cache-Control: public, max-age=31536000, immutable
    
    # HTML documents
    Cache-Control: no-cache
    
    # API responses
    Cache-Control: private, max-age=0, must-revalidate
  5. HTTP/2+ multiplexing
    • Verify protocol in DevTools Network tab
    • Multiple resources should load in parallel over single connection
分析网络瀑布流挖掘优化空间。
核心检查项:
  1. 资源数量与总大小
    • 目标:< 100个请求,总大小< 2MB(压缩后)
    • 检查方式:
      performance.getEntriesByType('resource').length
  2. 关键请求链
    • 识别长度超过3个请求的依赖链
    • 通过preload/prefetch提示打断长依赖链
  3. 压缩配置
    • 所有文本资源应使用Brotli(br)或gzip压缩
    • 检查响应头
      Content-Encoding
      确认配置
  4. 缓存头配置
    # 不可变资源(带哈希文件名)
    Cache-Control: public, max-age=31536000, immutable
    
    # HTML文档
    Cache-Control: no-cache
    
    # API响应
    Cache-Control: private, max-age=0, must-revalidate
  5. HTTP/2+多路复用
    • 在DevTools网络面板确认请求协议
    • 多资源应通过单连接并行加载

Phase 4: Accessibility Performance

阶段4:可访问性性能校验

Performance optimizations must not degrade accessibility.
Validation Checklist:
  • Lazy-loaded images have
    alt
    attributes
  • Deferred scripts do not break keyboard navigation
  • Skeleton loaders have
    aria-busy="true"
    and
    aria-label
  • prefers-reduced-motion
    is respected for animations
  • Focus management works with dynamically loaded content
css
/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
性能优化不能损害可访问性。
校验Checklist:
  • 懒加载图片配置了
    alt
    属性
  • 延迟加载的脚本不会破坏键盘导航
  • 骨架屏配置了
    aria-busy="true"
    aria-label
    属性
  • 动画尊重
    prefers-reduced-motion
    偏好设置
  • 焦点管理适配动态加载内容
css
/* 尊重减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Phase 5: Codebase Analysis

阶段5:代码库分析

Review source code for performance anti-patterns.
审查源代码中的性能反模式。

Webpack Optimization

Webpack优化

javascript
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 25,
      minSize: 20000,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
            return `vendor.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },
};
javascript
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 25,
      minSize: 20000,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
            return `vendor.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },
};

Vite Optimization

Vite优化

javascript
// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom'],
        },
      },
    },
    cssCodeSplit: true,
    sourcemap: false, // Disable in production
  },
});
javascript
// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom'],
        },
      },
    },
    cssCodeSplit: true,
    sourcemap: false, // 生产环境关闭
  },
});

Next.js Optimization

Next.js优化

typescript
// next.config.ts
const nextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200],
  },
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react'],
  },
};
typescript
// next.config.ts
const nextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200],
  },
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react'],
  },
};

Common Code Anti-Patterns

常见代码反模式

Anti-PatternImpactFix
Barrel file importsBundle bloatImport directly from module
Synchronous
localStorage
in render
Main thread blockMove to
useEffect
or worker
Unoptimized imagesLCP, bandwidthUse
next/image
or
<picture>
Inline
<script>
in body
Render blockingUse
async
or
defer
CSS
@import
chains
CSSOM blockingConcatenate or inline critical CSS
Unthrottled scroll listenersINPUse
passive: true
+
requestAnimationFrame
document.querySelectorAll
in loops
Layout thrashingCache DOM references
反模式影响修复方案
桶文件导入包体积膨胀直接从模块导入
渲染逻辑中同步调用
localStorage
主线程阻塞移至
useEffect
或Web Worker中
未优化的图片LCP下降、带宽浪费使用
next/image
<picture>
标签
body中内联
<script>
阻塞渲染使用
async
defer
属性
CSS
@import
依赖链
阻塞CSSOM构建拼接或内联关键CSS
未节流的滚动监听器INP下降使用
passive: true
+
requestAnimationFrame
循环中调用
document.querySelectorAll
布局抖动缓存DOM引用

Audit Report Template

审计报告模板

markdown
undefined
markdown
undefined

Web Performance Audit Report

Web性能审计报告

URL: [target URL] Date: [audit date] Tool: Lighthouse [version] / Chrome DevTools
URL: [目标站点URL] 审计日期: [审计日期] 审计工具: Lighthouse [版本号] / Chrome DevTools

Core Web Vitals Summary

Core Web Vitals汇总

MetricScoreRatingTarget
LCPX.XsGOOD/NEEDS IMPROVEMENT/POOR<= 2.5s
CLSX.XXGOOD/NEEDS IMPROVEMENT/POOR<= 0.1
INPXmsGOOD/NEEDS IMPROVEMENT/POOR<= 200ms
FCPX.Xs-<= 1.8s
TTFBXms-<= 800ms
TBTXms-<= 200ms
指标实际值评级目标值
LCPX.Xs优秀/需要改进/较差<= 2.5s
CLSX.XX优秀/需要改进/较差<= 0.1
INPXms优秀/需要改进/较差<= 200ms
FCPX.Xs-<= 1.8s
TTFBXms-<= 800ms
TBTXms-<= 200ms

Critical Findings

关键发现

P0 (Immediate Action Required)

P0(需立即修复)

  1. [Finding] - [Impact] - [Recommended Fix]
  1. [问题描述] - [影响范围] - [推荐修复方案]

P1 (Address This Sprint)

P1(当前迭代修复)

  1. [Finding] - [Impact] - [Recommended Fix]
  1. [问题描述] - [影响范围] - [推荐修复方案]

P2 (Address This Quarter)

P2(本季度修复)

  1. [Finding] - [Impact] - [Recommended Fix]
  1. [问题描述] - [影响范围] - [推荐修复方案]

Optimization Recommendations (Priority Order)

优化建议(按优先级排序)

  1. [Recommendation with estimated impact]
  2. [Recommendation with estimated impact]
  3. [Recommendation with estimated impact]
undefined
  1. [建议内容 + 预估收益]
  2. [建议内容 + 预估收益]
  3. [建议内容 + 预估收益]
undefined

Anti-Patterns

反模式

  • Do NOT optimize without measuring first -- always capture baseline metrics
  • Do NOT lazy-load above-the-fold content -- it worsens LCP
  • Do NOT remove image dimensions to "fix" CLS -- use CSS aspect-ratio instead
  • Do NOT bundle all JS into a single file -- use code splitting
  • Do NOT ignore mobile performance -- test with CPU/network throttling
  • Do NOT use
    loading="lazy"
    on the LCP image -- it delays loading
  • Do NOT serve images without modern formats (AVIF/WebP)
  • 禁止未测量先优化——始终先采集基准指标
  • 禁止懒加载首屏内容——会导致LCP恶化
  • 禁止移除图片尺寸来「修复」CLS——应使用CSS aspect-ratio替代
  • 禁止将所有JS打包为单文件——使用代码拆分
  • 禁止忽略移动端性能——使用CPU/网络节流测试
  • 禁止给LCP图片加
    loading="lazy"
    属性——会延迟加载
  • 禁止未提供现代格式(AVIF/WebP)的图片资源

References

参考资料

Iron Laws

铁律

  1. ALWAYS measure Core Web Vitals (LCP, INP, CLS) with field data (CrUX) before proposing optimizations
  2. NEVER optimize based on lab data alone — real user metrics determine actual user experience
  3. ALWAYS prioritize LCP ≤2.5s, INP ≤200ms, CLS ≤0.1 as the primary performance targets
  4. NEVER ship a performance fix without a before/after measurement proving improvement
  5. ALWAYS address critical rendering path issues before layout or paint optimizations
  1. 始终在提出优化方案前,通过真实用户数据(CrUX)测量Core Web Vitals(LCP、INP、CLS)
  2. 绝不仅基于实验室数据优化——真实用户指标才决定实际用户体验
  3. 始终将LCP ≤2.5s、INP ≤200ms、CLS ≤0.1作为核心性能目标
  4. 绝不上线性能修复方案前不做前后对比测量,需证明优化有效
  5. 始终优先解决关键渲染路径问题,再处理布局或绘制优化

Anti-Patterns

反模式对照表

Anti-PatternWhy It FailsCorrect Approach
Optimizing without baseline measurementCan't prove improvement, may optimize wrong thingMeasure CWV with Lighthouse and CrUX first
Lab-only metrics (Lighthouse only)Doesn't reflect real user network/device conditionsCombine lab data with CrUX field data
Fixing CLS before LCP is addressedLCP impacts far more users than CLSPrioritize in order: LCP → INP → CLS
Shipping without before/after metricsNo evidence of improvement for stakeholdersRecord pre-fix and post-fix CWV scores
Adding polyfills without code splittingBloats JS bundle for all usersUse dynamic
import()
with target browserslist
反模式问题风险正确方案
无基准测量直接优化无法证明优化效果,可能优化了错误的问题先通过Lighthouse和CrUX测量CWV指标
仅依赖实验室指标(仅Lighthouse)无法反映真实用户的网络/设备条件结合实验室数据与CrUX真实用户数据
LCP未达标先修复CLSLCP对用户的影响远大于CLS优先级排序:LCP → INP → CLS
无前后对比指标就上线修复无法向利益相关方证明优化效果记录修复前后的CWV分数
未做代码拆分就添加polyfill增加所有用户的JS包体积结合目标浏览器列表使用动态
import()

Memory Protocol (MANDATORY)

记录协议(强制要求)

Before starting: Read
.claude/context/memory/learnings.md
After completing:
  • New pattern ->
    .claude/context/memory/learnings.md
  • Issue found ->
    .claude/context/memory/issues.md
  • Decision made ->
    .claude/context/memory/decisions.md
开始前: 阅读
.claude/context/memory/learnings.md
完成后:
  • 新发现的模式 → 写入
    .claude/context/memory/learnings.md
  • 发现的问题 → 写入
    .claude/context/memory/issues.md
  • 做出的决策 → 写入
    .claude/context/memory/decisions.md