web-perf
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb 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阈值
| Metric | Good | Needs Improvement | Poor | What It Measures |
|---|---|---|---|---|
| LCP | <= 2.5s | 2.5s - 4.0s | > 4.0s | Loading performance |
| CLS | <= 0.1 | 0.1 - 0.25 | > 0.25 | Visual stability |
| INP | <= 200ms | 200ms - 500ms | > 500ms | Interactivity (replaced FID) |
| 指标 | 优秀 | 需要改进 | 较差 | 测量维度 |
|---|---|---|---|---|
| LCP | <= 2.5s | 2.5s - 4.0s | > 4.0s | 加载性能 |
| CLS | <= 0.1 | 0.1 - 0.25 | > 0.25 | 视觉稳定性 |
| INP | <= 200ms | 200ms - 500ms | > 500ms | 交互性(已取代FID) |
Additional Performance Metrics
额外性能指标
| Metric | Good | Poor | What It Measures |
|---|---|---|---|
| FCP | <= 1.8s | > 3.0s | First content rendered |
| TTFB | <= 800ms | > 1800ms | Server response time |
| TBT | <= 200ms | > 600ms | Main thread blocking |
| Speed Index | <= 3.4s | > 5.8s | Visual 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):
- Open Chrome DevTools (F12) > Performance tab
- Click "Record" and reload the page
- Stop recording after page fully loads
- 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):
- 打开Chrome DevTools(F12)> 性能面板
- 点击「录制」并重新加载页面
- 页面完全加载后停止录制
- 分析火焰图排查以下问题:
- 长任务(> 50ms,标记为红色)
- 布局抖动(强制重排循环)
- 阻塞渲染的资源
- JavaScript执行瓶颈
Lighthouse审计:
bash
undefinedCLI-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 < 500msnpx lighthouse https://example.com --preset=perf --throttling-method=simulate
**核心追踪指标:**
- **主线程忙碌总时长**:应< 4s
- **最大任务耗时**:应< 250ms
- **脚本执行时间**:应< 2s
- **布局/样式重计算耗时**:应< 500msPhase 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:
- elements (hero images)
<img> - poster images
<video> - Block-level elements with background images
- Text blocks (,
<h1>)<p>
LCP Optimization Checklist:
-
Preload the LCP resourcehtml
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" /> -
Eliminate render-blocking resourceshtml
<!-- 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> -
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
-
Optimize image deliveryhtml
<!-- 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:
-
预加载LCP资源html
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" /> -
移除阻塞渲染的资源html
<!-- 延迟加载非关键CSS --> <link rel="stylesheet" href="/non-critical.css" media="print" onload="this.media='all'" /> <!-- 异步加载非关键JS --> <script src="/analytics.js" async></script> -
优化服务器响应时间(TTFB)
- 静态资源使用CDN
- 启用HTTP/2或HTTP/3
- 实现服务端缓存
- 支持的场景下使用流式SSR
-
优化图片分发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:
-
Always set image dimensionshtml
<img src="/photo.jpg" width="800" height="600" alt="Photo" />Or use CSS aspect-ratio:css.hero-image { aspect-ratio: 16 / 9; width: 100%; } -
Reserve space for dynamic contentcss
.ad-slot { min-height: 250px; } .skeleton { height: 200px; background: #f0f0f0; } -
Usewith size-adjust
font-display: swapcss@font-face { font-family: 'CustomFont'; src: url('/font.woff2') format('woff2'); font-display: swap; size-adjust: 100.5%; /* Match fallback font metrics */ } -
Avoid inserting content above existing content
- Banners should push down from top, not shift existing content
- Use animations instead of
transform/top/left/widthheight
CLS衡量视觉稳定性——页面加载过程中意外布局偏移的程度。
常见CLS诱因:
- 未明确设置尺寸的图片
- 未预留占位空间的广告或嵌入内容
- 首屏区域动态注入的内容
- Web字体导致FOIT/FOUT(无样式文本闪烁/不可见文本闪烁)
CLS优化 Checklist:
-
始终设置图片尺寸html
<img src="/photo.jpg" width="800" height="600" alt="Photo" />或使用CSS aspect-ratio:css.hero-image { aspect-ratio: 16 / 9; width: 100%; } -
为动态内容预留占位空间css
.ad-slot { min-height: 250px; } .skeleton { height: 200px; background: #f0f0f0; } -
结合与size-adjust使用
font-display: swapcss@font-face { font-family: 'CustomFont'; src: url('/font.woff2') format('woff2'); font-display: swap; size-adjust: 100.5%; /* 匹配降级字体指标 */ } -
避免在已有内容上方插入新内容
- 横幅应从顶部向下推开内容,而非挤压已有内容产生偏移
- 动画使用而非
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:
-
Break up long tasksjavascript
// 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(); } } -
Debounce/throttle event handlersjavascript
// Throttle scroll handler let ticking = false; window.addEventListener( 'scroll', () => { if (!ticking) { requestAnimationFrame(() => { updateUI(); ticking = false; }); ticking = true; } }, { passive: true } ); -
Usefor non-urgent work
requestIdleCallbackjavascriptrequestIdleCallback(() => { // Analytics, prefetching, non-visible updates sendAnalytics(data); });
INP衡量交互性——用户交互到页面视觉响应之间的延迟。
常见INP诱因:
- 长JavaScript任务阻塞主线程
- 同步布局/样式重计算
- 过重的事件处理函数
- 过度重渲染(React、Vue)
INP优化 Checklist:
-
拆分长任务javascript
// 替换单长任务写法 function processAllItems(items) { for (const item of items) { /* 重计算逻辑 */ } } // 通过调度器拆分为多个小任务 async function processAllItems(items) { for (const item of items) { processItem(item); // 处理单个条目后让渡主线程 await scheduler.yield(); } } -
防抖/节流事件处理函数javascript
// 节流滚动处理函数 let ticking = false; window.addEventListener( 'scroll', () => { if (!ticking) { requestAnimationFrame(() => { updateUI(); ticking = false; }); ticking = true; } }, { passive: true } ); -
非紧急任务使用
requestIdleCallbackjavascriptrequestIdleCallback(() => { // 埋点上报、预加载、非可见区域更新等逻辑 sendAnalytics(data); });
Phase 3: Network Analysis
阶段3:网络分析
Analyze network waterfall for optimization opportunities.
Key Checks:
-
Resource count and total size
- Target: < 100 requests, < 2MB total (compressed)
- Check:
performance.getEntriesByType('resource').length
-
Critical request chains
- Identify chains longer than 3 requests
- Break chains with preload/prefetch hints
-
Compression
- All text resources should use Brotli (br) or gzip
- Check header in response
Content-Encoding
-
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 -
HTTP/2+ multiplexing
- Verify protocol in DevTools Network tab
- Multiple resources should load in parallel over single connection
分析网络瀑布流挖掘优化空间。
核心检查项:
-
资源数量与总大小
- 目标:< 100个请求,总大小< 2MB(压缩后)
- 检查方式:
performance.getEntriesByType('resource').length
-
关键请求链
- 识别长度超过3个请求的依赖链
- 通过preload/prefetch提示打断长依赖链
-
压缩配置
- 所有文本资源应使用Brotli(br)或gzip压缩
- 检查响应头确认配置
Content-Encoding
-
缓存头配置
# 不可变资源(带哈希文件名) Cache-Control: public, max-age=31536000, immutable # HTML文档 Cache-Control: no-cache # API响应 Cache-Control: private, max-age=0, must-revalidate -
HTTP/2+多路复用
- 在DevTools网络面板确认请求协议
- 多资源应通过单连接并行加载
Phase 4: Accessibility Performance
阶段4:可访问性性能校验
Performance optimizations must not degrade accessibility.
Validation Checklist:
- Lazy-loaded images have attributes
alt - Deferred scripts do not break keyboard navigation
- Skeleton loaders have and
aria-busy="true"aria-label - is respected for animations
prefers-reduced-motion - 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-Pattern | Impact | Fix |
|---|---|---|
| Barrel file imports | Bundle bloat | Import directly from module |
Synchronous | Main thread block | Move to |
| Unoptimized images | LCP, bandwidth | Use |
Inline | Render blocking | Use |
CSS | CSSOM blocking | Concatenate or inline critical CSS |
| Unthrottled scroll listeners | INP | Use |
| Layout thrashing | Cache DOM references |
| 反模式 | 影响 | 修复方案 |
|---|---|---|
| 桶文件导入 | 包体积膨胀 | 直接从模块导入 |
渲染逻辑中同步调用 | 主线程阻塞 | 移至 |
| 未优化的图片 | LCP下降、带宽浪费 | 使用 |
body中内联 | 阻塞渲染 | 使用 |
CSS | 阻塞CSSOM构建 | 拼接或内联关键CSS |
| 未节流的滚动监听器 | INP下降 | 使用 |
循环中调用 | 布局抖动 | 缓存DOM引用 |
Audit Report Template
审计报告模板
markdown
undefinedmarkdown
undefinedWeb 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汇总
| Metric | Score | Rating | Target |
|---|---|---|---|
| LCP | X.Xs | GOOD/NEEDS IMPROVEMENT/POOR | <= 2.5s |
| CLS | X.XX | GOOD/NEEDS IMPROVEMENT/POOR | <= 0.1 |
| INP | Xms | GOOD/NEEDS IMPROVEMENT/POOR | <= 200ms |
| FCP | X.Xs | - | <= 1.8s |
| TTFB | Xms | - | <= 800ms |
| TBT | Xms | - | <= 200ms |
| 指标 | 实际值 | 评级 | 目标值 |
|---|---|---|---|
| LCP | X.Xs | 优秀/需要改进/较差 | <= 2.5s |
| CLS | X.XX | 优秀/需要改进/较差 | <= 0.1 |
| INP | Xms | 优秀/需要改进/较差 | <= 200ms |
| FCP | X.Xs | - | <= 1.8s |
| TTFB | Xms | - | <= 800ms |
| TBT | Xms | - | <= 200ms |
Critical Findings
关键发现
P0 (Immediate Action Required)
P0(需立即修复)
- [Finding] - [Impact] - [Recommended Fix]
- [问题描述] - [影响范围] - [推荐修复方案]
P1 (Address This Sprint)
P1(当前迭代修复)
- [Finding] - [Impact] - [Recommended Fix]
- [问题描述] - [影响范围] - [推荐修复方案]
P2 (Address This Quarter)
P2(本季度修复)
- [Finding] - [Impact] - [Recommended Fix]
- [问题描述] - [影响范围] - [推荐修复方案]
Optimization Recommendations (Priority Order)
优化建议(按优先级排序)
- [Recommendation with estimated impact]
- [Recommendation with estimated impact]
- [Recommendation with estimated impact]
undefined- [建议内容 + 预估收益]
- [建议内容 + 预估收益]
- [建议内容 + 预估收益]
undefinedAnti-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 on the LCP image -- it delays loading
loading="lazy" - Do NOT serve images without modern formats (AVIF/WebP)
- 禁止未测量先优化——始终先采集基准指标
- 禁止懒加载首屏内容——会导致LCP恶化
- 禁止移除图片尺寸来「修复」CLS——应使用CSS aspect-ratio替代
- 禁止将所有JS打包为单文件——使用代码拆分
- 禁止忽略移动端性能——使用CPU/网络节流测试
- 禁止给LCP图片加属性——会延迟加载
loading="lazy" - 禁止未提供现代格式(AVIF/WebP)的图片资源
References
参考资料
Iron Laws
铁律
- ALWAYS measure Core Web Vitals (LCP, INP, CLS) with field data (CrUX) before proposing optimizations
- NEVER optimize based on lab data alone — real user metrics determine actual user experience
- ALWAYS prioritize LCP ≤2.5s, INP ≤200ms, CLS ≤0.1 as the primary performance targets
- NEVER ship a performance fix without a before/after measurement proving improvement
- ALWAYS address critical rendering path issues before layout or paint optimizations
- 始终在提出优化方案前,通过真实用户数据(CrUX)测量Core Web Vitals(LCP、INP、CLS)
- 绝不仅基于实验室数据优化——真实用户指标才决定实际用户体验
- 始终将LCP ≤2.5s、INP ≤200ms、CLS ≤0.1作为核心性能目标
- 绝不上线性能修复方案前不做前后对比测量,需证明优化有效
- 始终优先解决关键渲染路径问题,再处理布局或绘制优化
Anti-Patterns
反模式对照表
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
| Optimizing without baseline measurement | Can't prove improvement, may optimize wrong thing | Measure CWV with Lighthouse and CrUX first |
| Lab-only metrics (Lighthouse only) | Doesn't reflect real user network/device conditions | Combine lab data with CrUX field data |
| Fixing CLS before LCP is addressed | LCP impacts far more users than CLS | Prioritize in order: LCP → INP → CLS |
| Shipping without before/after metrics | No evidence of improvement for stakeholders | Record pre-fix and post-fix CWV scores |
| Adding polyfills without code splitting | Bloats JS bundle for all users | Use dynamic |
| 反模式 | 问题风险 | 正确方案 |
|---|---|---|
| 无基准测量直接优化 | 无法证明优化效果,可能优化了错误的问题 | 先通过Lighthouse和CrUX测量CWV指标 |
| 仅依赖实验室指标(仅Lighthouse) | 无法反映真实用户的网络/设备条件 | 结合实验室数据与CrUX真实用户数据 |
| LCP未达标先修复CLS | LCP对用户的影响远大于CLS | 优先级排序:LCP → INP → CLS |
| 无前后对比指标就上线修复 | 无法向利益相关方证明优化效果 | 记录修复前后的CWV分数 |
| 未做代码拆分就添加polyfill | 增加所有用户的JS包体积 | 结合目标浏览器列表使用动态 |
Memory Protocol (MANDATORY)
记录协议(强制要求)
Before starting:
Read
.claude/context/memory/learnings.mdAfter 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