Skip to content
advanced Phase 15 · Performance Optimization and Lazy Loading

Measuring Core Web Vitals

Track loading and responsiveness metrics in the field.

40m
0 problems
Topic Progress 0%

Core Web Vitals Metrics

Core Web Vitals are Google's standardized performance metrics that directly impact search rankings and user experience.

LCP — Largest Contentful Paint

Measures when the largest visible content element renders.

Rating Threshold
Good ≤ 2.5s
Needs Improvement 2.5s - 4.0s
Poor > 4.0s

Common LCP issues in Angular:

  • Large images without optimization
  • Render-blocking JavaScript
  • Slow server response times (use SSR)
  • Large bundles delaying hydration

INP — Interaction to Next Paint

Measures responsiveness across the whole visit (replaces FID).

Rating Threshold
Good ≤ 200ms
Needs Improvement 200ms - 500ms
Poor > 500ms

Common INP issues in Angular:

  • Long change detection cycles
  • Expensive event handlers
  • Main thread blocked by heavy computation
  • Excessive DOM updates

CLS — Cumulative Layout Shift

Measures visual stability (unexpected layout shifts).

Rating Threshold
Good ≤ 0.1
Needs Improvement 0.1 - 0.25
Poor > 0.25

Common CLS issues in Angular:

  • Images without explicit dimensions
  • Dynamically injected content
  • Late-loading fonts
  • Components that change size after render

Monitoring and Budgets

Track Core Web Vitals in the field and enforce budgets in CI.

Web Vitals Library

npm install web-vitals
import { onLCP, onINP, onCLS } from 'web-vitals';

export function reportWebVitals(): void {
  onLCP(metric => {
    console.log('LCP:', metric.value);
  });

  onINP(metric => {
    console.log('INP:', metric.value);
  });

  onCLS(metric => {
    console.log('CLS:', metric.value);
  });
}

Route-Level Performance Budgets

{
  "architect": {
    "build": {
      "configurations": {
        "production": {
          "budgets": [
            {
              "type": "initial",
              "maximumWarning": "500kb",
              "maximumError": "1mb"
            },
            {
              "type": "anyComponentStyle",
              "maximumWarning": "2kb",
              "maximumError": "4kb"
            }
          ]
        }
      }
    }
  }
}

Lighthouse CI

npm install @lhci/cli --save-dev
// lighthouserc.json
{
  "ci": {
    "collect": {
      "url": ["http://localhost:8080"]
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.9 }],
        "categories:accessibility": ["error", { "minScore": 0.9 }]
      }
    }
  }
}

Performance Optimization Checklist

  • LCP < 2.5s (optimize images, use SSR, reduce bundle size)
  • INP < 200ms (use OnPush, signals, avoid long tasks)
  • CLS < 0.1 (set image dimensions, reserve space for dynamic content)
  • Lighthouse performance score > 90
  • Accessibility score > 90
  • Route-level budgets enforced in CI

Quiz

1. What does LCP measure?

Question 1 options

2. What does INP measure?

Question 2 options

3. What causes CLS (layout shift)?

Question 3 options

Flashcards

Question

What does LCP measure?

Answer

When largest visible content renders. Good: ≤ 2.5s.

Question

What does INP measure?

Answer

Responsiveness across whole visit. Good: ≤ 200ms.

Question

What causes CLS?

Answer

Layout shifts: images without dimensions, dynamic content, late fonts.

Revision Notes

Key Takeaways

  • 1. LCP measures largest content render time
  • 2. INP measures interaction responsiveness
  • 3. CLS measures visual stability
  • 4. Enforce budgets in CI with Lighthouse

Interview Tips

  • • Explain each Core Web Vital metric
  • • Be ready to describe optimization strategies
  • • Mention field monitoring with web-vitals library

Cheat Sheet

Core Web Vitals Cheat Sheet

LCP (Largest Contentful Paint):

  • Good: ≤ 2.5s
  • Optimize images, use SSR, reduce bundle size

INP (Interaction to Next Paint):

  • Good: ≤ 200ms
  • Use OnPush, signals, avoid long tasks

CLS (Cumulative Layout Shift):

  • Good: ≤ 0.1
  • Set image dimensions, reserve space for dynamic content

Monitoring:

import { onLCP, onINP, onCLS } from 'web-vitals';

Continue Learning