performance-review

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Performance Review

性能评估

Measure and evaluate your application's performance against Google's Core Web Vitals thresholds and industry benchmarks. This review catches performance issues that are invisible during development but impact real users — bundle bloat, layout shifts, slow interactions, unoptimized images, and render-blocking resources.
对照Google的Core Web Vitals阈值和行业基准,衡量并评估你的应用性能。本次评估会捕捉开发阶段不易察觉但影响真实用户的性能问题——包体积臃肿、布局偏移、交互缓慢、未优化图片以及阻塞渲染的资源。

When to use

适用场景

Use
/performance-review
when:
  • Before launching or after major feature additions
  • Page load feels slow but you're not sure why
  • Preparing for high-traffic events
  • After adding new dependencies or third-party scripts
  • SEO rankings depend on performance scores
  • Users report slowness or abandonment
在以下场景使用
/performance-review
  • 应用上线前或添加重大功能后
  • 页面加载感觉缓慢但找不到原因时
  • 为高流量活动做准备时
  • 添加新依赖或第三方脚本后
  • SEO排名依赖性能得分时
  • 用户反馈页面卡顿或出现流失情况时

Standards Referenced

参考标准

  • Google Core Web Vitals — LCP, INP, CLS (2024 thresholds)
  • Google Lighthouse — Performance scoring methodology
  • HTTP Archive — Web performance benchmarks (median, p75, p90)
  • Web.dev Performance Guidelines — Best practices
  • RAIL Model — Response, Animation, Idle, Load budgets
  • Google Core Web Vitals — LCP、INP、CLS(2024年阈值)
  • Google Lighthouse — 性能评分方法
  • HTTP Archive — Web性能基准数据(中位数、p75、p90)
  • Web.dev Performance Guidelines — 最佳实践
  • RAIL Model — 响应、动画、空闲、加载预算模型

Phase Overview

阶段概述

Phase 1: EDUCATE   → Performance impact on business and what we measure
Phase 2: SCOPE     → Identify key pages, performance budget, baseline
Phase 3: ANALYZE   → Browser-based performance measurement
Phase 4: REPORT    → Findings with metrics, scores, and comparisons
Phase 5: REMEDIATE → Fix guidance + YAML regression tests

Phase 1: EDUCATE   → 性能对业务的影响及测量指标说明
Phase 2: SCOPE     → 确定关键页面、性能预算与基准线
Phase 3: ANALYZE   → 基于浏览器的性能测量
Phase 4: REPORT    → 包含指标、得分与对比分析的结果报告
Phase 5: REMEDIATE → 修复指导 + YAML回归测试

Phase 1: Educate

阶段1:认知普及

Why this matters: A 1-second delay in page load reduces conversions by 7% (Akamai). Google uses Core Web Vitals as ranking signals since 2021. 53% of mobile visitors leave a page that takes >3 seconds to load (Google). Amazon found every 100ms of latency costs 1% of sales. Performance is a feature — and its absence is a bug.
This review measures real performance in a browser, not just static analysis. We capture actual load times, rendering behavior, and interaction responsiveness.

重要性说明: 页面加载延迟1秒会导致转化率下降7%(Akamai数据)。自2021年起,Google将Core Web Vitals作为排名信号。53%的移动访客会离开加载时间超过3秒的页面(Google数据)。亚马逊发现每100毫秒的延迟会导致1%的销售额损失。性能是一项功能——缺失性能就是一个bug。
本次评估在浏览器中测量真实性能,而非仅做静态分析。我们会捕捉实际加载时间、渲染行为和交互响应速度。

Phase 2: Scope

阶段2:范围界定

Gather context

收集上下文信息

  1. Auto-detect from codebase:
    • Build system (Webpack, Vite, Next.js, etc.)
    • Bundle analysis setup (if any)
    • Image optimization pipeline (sharp, next/image, etc.)
    • Font loading strategy
    • Code splitting configuration
    • Service worker / caching strategy
    • CDN configuration
  2. Ask the user (one at a time):
    • Target URL: Where is the app running? (production preferred for realistic measurements)
    • Key pages: Which pages matter most for performance? (recommend: landing page, main feature page, data-heavy page)
    • Performance budget: Any existing targets? (default: Core Web Vitals "Good" thresholds)
    • Known concerns: Any pages that feel slow? (optional)
  3. Define measurement plan:
    • Pages to test (3-5 key pages)
    • Conditions: desktop and mobile simulated (Moto G4 / Slow 4G)
    • Metrics: Core Web Vitals + supplementary metrics
    • Baseline: first run establishes baseline for comparison

  1. 从代码库自动检测:
    • 构建系统(Webpack、Vite、Next.js等)
    • 包分析配置(如有)
    • 图片优化流程(sharp、next/image等)
    • 字体加载策略
    • 代码分割配置
    • Service Worker/缓存策略
    • CDN配置
  2. 向用户询问(逐一进行):
    • 目标URL:应用部署在哪里?(优先选择生产环境以获取真实测量数据)
    • 关键页面:哪些页面的性能最为重要?(推荐:首页、核心功能页、数据密集型页面)
    • 性能预算:是否有既定目标?(默认:Core Web Vitals的「良好」阈值)
    • 已知问题:是否有页面感觉卡顿?(可选)
  3. 制定测量计划:
    • 测试页面(3-5个关键页面)
    • 测试条件:模拟桌面端和移动端(Moto G4 / 慢速4G网络)
    • 测量指标:Core Web Vitals + 补充指标
    • 基准线:首次测量结果作为后续对比的基准

Phase 3: Analyze

阶段3:分析测试

Open a browser session with
new_session
using
record_evidence: true
. For each page in scope, run all measurement categories.
使用
new_session
开启浏览器会话并设置
record_evidence: true
。对每个范围内的页面,运行所有测量类别。

Category A: Core Web Vitals (CWV)

类别A:Core Web Vitals(CWV)

Check IDMetricGoodNeeds ImprovementPoorMethod
CWV-01LCP (Largest Contentful Paint)≤2.5s2.5-4.0s>4.0s
PerformanceObserver
for LCP entries
CWV-02INP (Interaction to Next Paint)≤200ms200-500ms>500msClick key interactive elements, measure delay
CWV-03CLS (Cumulative Layout Shift)≤0.10.1-0.25>0.25
PerformanceObserver
for layout-shift entries
Browser validation: Navigate to each page and capture metrics via JavaScript:
javascript
// LCP
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lcp = entries[entries.length - 1];
  console.log('LCP:', lcp.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });

// CLS
let clsValue = 0;
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) clsValue += entry.value;
  }
  console.log('CLS:', clsValue);
}).observe({ type: 'layout-shift', buffered: true });
检查ID指标良好需要改进较差方法
CWV-01LCP(Largest Contentful Paint)≤2.5s2.5-4.0s>4.0s
PerformanceObserver
监听LCP条目
CWV-02INP(Interaction to Next Paint)≤200ms200-500ms>500ms点击关键交互元素,测量延迟
CWV-03CLS(Cumulative Layout Shift)≤0.10.1-0.25>0.25
PerformanceObserver
监听布局偏移条目
浏览器验证: 导航至每个页面,通过JavaScript捕获指标:
javascript
// LCP
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lcp = entries[entries.length - 1];
  console.log('LCP:', lcp.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });

// CLS
let clsValue = 0;
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) clsValue += entry.value;
  }
  console.log('CLS:', clsValue);
}).observe({ type: 'layout-shift', buffered: true });

Category B: Page Load Performance (LOAD)

类别B:页面加载性能(LOAD)

Check IDCheckThresholdMethod
LOAD-01Time to First Byte (TTFB)≤800ms
performance.timing.responseStart - navigationStart
LOAD-02First Contentful Paint (FCP)≤1.8s
performance.getEntriesByName('first-contentful-paint')
LOAD-03DOM Content Loaded≤2.0s
performance.timing.domContentLoadedEventEnd
LOAD-04Total page weight≤3MB (mobile) / ≤5MB (desktop)
performance.getEntriesByType('resource')
sum
LOAD-05Number of HTTP requests≤50Count resource entries
LOAD-06Time to Interactive (TTI)≤3.8sLong task analysis
LOAD-07Total Blocking Time (TBT)≤200msSum of long tasks (>50ms portions)
LOAD-08Speed Index≤3.4sVisual progress analysis
Browser validation: Use Performance API and
performance.getEntries()
to gather all metrics.
检查ID检查项阈值方法
LOAD-01首字节时间(TTFB)≤800ms
performance.timing.responseStart - navigationStart
LOAD-02首次内容绘制(FCP)≤1.8s
performance.getEntriesByName('first-contentful-paint')
LOAD-03DOM内容加载完成≤2.0s
performance.timing.domContentLoadedEventEnd
LOAD-04页面总大小≤3MB(移动端)/ ≤5MB(桌面端)汇总
performance.getEntriesByType('resource')
的大小
LOAD-05HTTP请求数量≤50统计资源条目数量
LOAD-06可交互时间(TTI)≤3.8s长任务分析
LOAD-07总阻塞时间(TBT)≤200ms汇总长任务中超过50ms的部分
LOAD-08速度指数≤3.4s视觉进度分析
浏览器验证: 使用Performance API和
performance.getEntries()
收集所有指标。

Category C: Resource Optimization (RES)

类别C:资源优化(RES)

Check IDCheckStandardMethod
RES-01Images use modern formats (WebP/AVIF)Web.devCheck image URLs and Content-Type
RES-02Images are appropriately sized (not oversized)Web.devCompare display size vs natural size
RES-03Images use lazy loading (below-fold)Web.devCheck
loading="lazy"
on below-fold images
RES-04Images have explicit dimensions (width/height)CLS preventionCheck for width/height attributes
RES-05CSS is not render-blocking (or is critical-inlined)Web.devCheck CSS loading strategy
RES-06JavaScript is deferred or asyncWeb.devCheck script loading attributes
RES-07Fonts use font-display: swap or optionalWeb.devCheck @font-face declarations
RES-08Fonts are preloadedWeb.devCheck for
<link rel="preload" as="font">
RES-09Gzip/Brotli compression enabledHTTP best practiceCheck Content-Encoding headers
RES-10HTTP/2 or HTTP/3 in useHTTP best practiceCheck protocol via Performance API
RES-11Effective caching headersHTTP best practiceCheck Cache-Control on static assets
RES-12No unused CSS/JS loadedBundle efficiencyCheck coverage via Page.startJSCoverage/startCSSCoverage
Browser validation: Use JavaScript to inspect all loaded resources, their types, sizes, and loading attributes. Use
performance.getEntriesByType('resource')
for detailed resource metrics.
检查ID检查项标准方法
RES-01图片使用现代格式(WebP/AVIF)Web.dev检查图片URL和Content-Type
RES-02图片尺寸合适(未过度放大)Web.dev对比显示尺寸与原始尺寸
RES-03折叠下方图片使用懒加载Web.dev检查折叠下方图片的
loading="lazy"
属性
RES-04图片设置明确尺寸(宽/高)预防CLS检查width/height属性
RES-05CSS未阻塞渲染(或已内联关键CSS)Web.dev检查CSS加载策略
RES-06JavaScript已延迟或异步加载Web.dev检查脚本加载属性
RES-07字体使用font-display: swap或optionalWeb.dev检查@font-face声明
RES-08字体已预加载Web.dev检查
<link rel="preload" as="font">
RES-09启用Gzip/Brotli压缩HTTP最佳实践检查Content-Encoding响应头
RES-10使用HTTP/2或HTTP/3HTTP最佳实践通过Performance API检查协议
RES-11缓存头配置有效HTTP最佳实践检查静态资源的Cache-Control
RES-12未加载未使用的CSS/JS包效率通过Page.startJSCoverage/startCSSCoverage检查覆盖率
浏览器验证: 使用JavaScript检查所有已加载资源的类型、大小和加载属性。使用
performance.getEntriesByType('resource')
获取详细资源指标。

Category D: Bundle Analysis (BUN)

类别D:包分析(BUN)

Check IDCheckThresholdMethod
BUN-01Main JS bundle size≤250KB gzippedCheck transfer size of main bundle
BUN-02Total JS size≤500KB gzippedSum all JS transfer sizes
BUN-03Total CSS size≤100KB gzippedSum all CSS transfer sizes
BUN-04Code splitting implementedBest practiceCheck for multiple JS chunks
BUN-05No duplicate dependenciesBundle efficiencyAnalyze chunk contents for duplicates
BUN-06Tree shaking effectiveBundle efficiencyCheck for known large unused exports
BUN-07Source maps not exposed in productionSecurity/PerformanceCheck for .map files accessibility
BUN-08Third-party JS budget≤30% of total JSCalculate third-party vs first-party ratio
Browser validation: Use Performance API to measure transfer sizes. Check for source map URLs. Analyze script domain origins.
检查ID检查项阈值方法
BUN-01主JS包大小≤250KB(gzip压缩后)检查主包的传输大小
BUN-02JS总大小≤500KB(gzip压缩后)汇总所有JS的传输大小
BUN-03CSS总大小≤100KB(gzip压缩后)汇总所有CSS的传输大小
BUN-04已实现代码分割最佳实践检查是否存在多个JS chunk
BUN-05无重复依赖包效率分析chunk内容查找重复项
BUN-06Tree Shaking生效包效率检查已知的大型未使用导出
BUN-07生产环境未暴露Source Maps安全/性能检查.map文件的可访问性
BUN-08第三方JS占比≤总JS的30%计算第三方与第一方JS的比例
浏览器验证: 使用Performance API测量传输大小。检查Source Map URL。分析脚本的域名来源。

Category E: Runtime Performance (RUN)

类别E:运行时性能(RUN)

Check IDCheckThresholdMethod
RUN-01No long tasks during interaction>50ms = long taskUse
PerformanceObserver
for long tasks
RUN-02Scroll performance is smooth60fpsScroll page, measure frame drops
RUN-03Animation performance60fpsTrigger animations, measure jank
RUN-04Memory usage is stable (no leaks)No growth patternMeasure
performance.memory
over time
RUN-05No excessive DOM nodes≤1500 nodesCount
document.querySelectorAll('*').length
RUN-06No layout thrashing0 forced reflowsMonitor forced style recalculations
RUN-07Efficient event listenersNo excessive listenersCheck for scroll/resize listeners without throttle
Browser validation: Navigate and interact with the app while measuring performance metrics via JavaScript.

检查ID检查项阈值方法
RUN-01交互过程中无长任务>50ms = 长任务使用
PerformanceObserver
监听长任务
RUN-02滚动性能流畅60fps滚动页面,测量掉帧情况
RUN-03动画性能60fps触发动画,测量卡顿
RUN-04内存使用稳定(无泄漏)无持续增长趋势长期监测
performance.memory
RUN-05DOM节点数量不过多≤1500个统计
document.querySelectorAll('*').length
RUN-06无布局抖动0次强制重排监测强制样式重计算
RUN-07事件监听器高效无过多监听器检查无节流的scroll/resize监听器
浏览器验证: 在导航和交互应用的同时,通过JavaScript测量性能指标。

Phase 4: Report

阶段4:生成报告

Generate a structured report saved to
shiplight/reports/performance-review-{date}.md
:
markdown
undefined
生成结构化报告并保存至
shiplight/reports/performance-review-{date}.md
markdown
undefined

Performance Review Report

性能评估报告

Date: {date} URL: {url} Pages tested: {list} Conditions: Desktop + Mobile (simulated Moto G4 / Slow 4G)
日期: {date} URL: {url} 测试页面: {list} 测试条件: 桌面端 + 移动端(模拟Moto G4 / 慢速4G)

Overall Score: {X}/10 | Confidence: {X}%

总体得分:{X}/10 | 置信度:{X}%

Core Web Vitals Summary

Core Web Vitals汇总

MetricDesktopMobileStatus
LCP1.8s3.2s⚠️ Mobile needs work
INP95ms180ms✅ Good
CLS0.050.15⚠️ Mobile needs work
指标桌面端移动端状态
LCP1.8s3.2s⚠️ 移动端需优化
INP95ms180ms✅ 良好
CLS0.050.15⚠️ 移动端需优化

Score Breakdown

得分细分

CategoryScoreFindings
Core Web Vitals (CWV)6/101 high, 1 medium
Page Load (LOAD)7/101 high
Resources (RES)5/102 high, 2 medium
Bundle (BUN)6/101 high, 1 medium
Runtime (RUN)8/101 medium
类别得分发现
Core Web Vitals (CWV)6/101个高优先级问题,1个中优先级问题
页面加载 (LOAD)7/101个高优先级问题
资源优化 (RES)5/102个高优先级问题,2个中优先级问题
包分析 (BUN)6/101个高优先级问题,1个中优先级问题
运行时性能 (RUN)8/101个中优先级问题

Resource Waterfall

资源加载瀑布图

(Top 10 slowest resources with load times)
(加载最慢的10个资源及加载时间)

Bundle Breakdown

包大小细分

CategorySize (gzipped)BudgetStatus
First-party JS180KB250KB
Third-party JS220KB150KB❌ Over budget
CSS45KB100KB
Images1.2MB1.5MB
Fonts85KB100KB
类别大小(gzip压缩后)预算状态
第一方JS180KB250KB
第三方JS220KB150KB❌ 超出预算
CSS45KB100KB
图片1.2MB1.5MB
字体85KB100KB

Findings

问题发现

(structured findings with metrics and evidence)
undefined
(包含指标和证据的结构化内容)
undefined

Confidence Scoring

置信度评分

  • 90-100%: Measured in browser with specific values (e.g., LCP: 3.2s)
  • 70-89%: Derived from resource analysis (e.g., unoptimized images detected)
  • 50-69%: Code-level pattern (e.g., no lazy loading attributes found)
  • Below 50%: Don't report

  • 90-100%:在浏览器中测量得到具体数值(如:LCP: 3.2s)
  • 70-89%:通过资源分析得出(如:检测到未优化图片)
  • 50-69%:基于代码模式判断(如:未找到懒加载属性)
  • 低于50%:不纳入报告

Phase 5: Remediate

阶段5:修复优化

1. Fix guidance (example)

1. 修复指导(示例)

markdown
undefined
markdown
undefined

RES-01: Images not using modern formats

RES-01:图片未使用现代格式

Impact: ~40% larger images than necessary, adds ~500KB to page weight Current: 8 PNG images totaling 1.2MB Fix: Convert to WebP with fallback:
  • Use
    <picture>
    with WebP source and PNG fallback
  • Or use Next.js
    <Image>
    /
    sharp
    for automatic format negotiation
  • Expected savings: ~480KB (40% reduction) Priority files:
  • /images/hero.png (320KB → ~190KB as WebP)
  • /images/features.png (280KB → ~165KB as WebP)
undefined
影响: 图片体积比必要情况大40%,增加约500KB页面大小 现状: 8张PNG图片总计1.2MB 修复方案: 转换为WebP格式并提供降级方案:
  • 使用
    <picture>
    标签,包含WebP源和PNG降级选项
  • 或使用Next.js
    <Image>
    /
    sharp
    自动协商格式
  • 预期节省:约480KB(减少40%) 优先处理文件:
  • /images/hero.png(320KB → WebP格式约190KB)
  • /images/features.png(280KB → WebP格式约165KB)
undefined

2. YAML regression test

2. YAML回归测试

yaml
- name: cwv-01-lcp-under-threshold
  description: Verify Largest Contentful Paint is under 2.5 seconds
  severity: high
  standard: Core-Web-Vitals-LCP
  steps:
    - description: Set up an LCP observer before navigation
      js: |
        // Set up LCP observer before navigation
        await page.evaluateOnNewDocument(() => {
          window.__lcp = 0;
          new PerformanceObserver((list) => {
            const entries = list.getEntries();
            window.__lcp = entries[entries.length - 1].startTime;
          }).observe({ type: 'largest-contentful-paint', buffered: true });
        });
    - URL: /
    - WAIT_UNTIL: Page has fully loaded including all images and content
      timeout_seconds: 30
    - description: Assert Largest Contentful Paint is under 2.5s
      js: |
        const lcp = await page.evaluate(() => window.__lcp);
        if (lcp > 2500) {
          throw new Error(`LCP is ${lcp}ms, exceeds 2500ms threshold`);
        }
        console.log(`LCP: ${lcp}ms (threshold: 2500ms)`);
    - VERIFY: Page loaded with Largest Contentful Paint under 2.5 seconds
Save all YAML tests to
shiplight/tests/performance-review.test.yaml
.

yaml
- name: cwv-01-lcp-under-threshold
  description: Verify Largest Contentful Paint is under 2.5 seconds
  severity: high
  standard: Core-Web-Vitals-LCP
  steps:
    - description: Set up an LCP observer before navigation
      js: |
        // Set up LCP observer before navigation
        await page.evaluateOnNewDocument(() => {
          window.__lcp = 0;
          new PerformanceObserver((list) => {
            const entries = list.getEntries();
            window.__lcp = entries[entries.length - 1].startTime;
          }).observe({ type: 'largest-contentful-paint', buffered: true });
        });
    - URL: /
    - WAIT_UNTIL: Page has fully loaded including all images and content
      timeout_seconds: 30
    - description: Assert Largest Contentful Paint is under 2.5s
      js: |
        const lcp = await page.evaluate(() => window.__lcp);
        if (lcp > 2500) {
          throw new Error(`LCP is ${lcp}ms, exceeds 2500ms threshold`);
        }
        console.log(`LCP: ${lcp}ms (threshold: 2500ms)`);
    - VERIFY: Page loaded with Largest Contentful Paint under 2.5 seconds
将所有YAML测试保存至
shiplight/tests/performance-review.test.yaml

Depth Levels

测试深度级别

  • --quick
    : Core Web Vitals only on the main page. ~2 minutes.
  • default: All categories on key pages, desktop + mobile. ~8-12 minutes.
  • --thorough
    : All categories + extended pages + multiple runs for statistical confidence + runtime profiling. ~20-30 minutes.
  • --quick
    :仅在主页面测试Core Web Vitals。耗时约2分钟。
  • 默认:在关键页面测试所有类别,覆盖桌面端和移动端。耗时约8-12分钟。
  • --thorough
    :测试所有类别+扩展页面+多次运行以获取统计置信度+运行时分析。耗时约20-30分钟。

Tips

小贴士

  • Measure on production (or production-like build) — dev mode performance is misleading
  • Run multiple times — performance measurements vary; look for patterns, not single data points
  • Mobile simulation reveals issues that desktop hides — always test both
  • Use
    performance.getEntries()
    — it's the richest source of performance data in the browser
  • Focus on Core Web Vitals first — they're the metrics Google uses for ranking
  • Close session with
    close_session
    and use
    generate_html_report
    for evidence
  • 在生产环境(或类生产构建)中测量——开发模式的性能数据具有误导性
  • 多次运行测试——性能测量结果会有波动;关注规律而非单个数据点
  • 移动端模拟会暴露桌面端隐藏的问题——务必同时测试两端
  • 使用
    performance.getEntries()
    ——它是浏览器中最丰富的性能数据源
  • 优先关注Core Web Vitals——它们是Google用于排名的指标
  • 使用
    close_session
    关闭会话,并通过
    generate_html_report
    生成证据报告