Mastering Web Performance: Essential Metrics Every Frontend Engineer Should Know
This article explains the core web performance metrics—First Paint, First Contentful Paint, Time to Interactive, Largest Contentful Paint, and First Meaningful Paint—along with how to retrieve them via the Performance API, calculate them, and interpret their impact on user experience.
Introduction
When interviewers ask about page performance metrics, candidates often answer with generic optimizations like file merging or resource compression; it’s time to review the actual performance indicators.
1. Basic Metrics Introduction
First Paint (FP)
First Contentful Paint (FCP)
Time to Interactive (TTI)
Largest Contentful Paint (LCP)
First Meaningful Paint (FMP)
FP marks the first moment the browser starts displaying any content after receiving the URL request.
FCP is the time when the browser first renders any text, image (including background images), non‑white canvas, or SVG. It is not merely the first screen render event.
TTI indicates when the page becomes fully interactive—UI components respond to clicks or input, and the main thread’s tasks stay under 50 ms, providing a smooth experience.
FMP was once used to estimate when the main content appears, but its algorithm only achieved about 77 % accuracy and was deprecated in Lighthouse 6.0 in favor of LCP.
LCP measures the time when the largest visible element in the viewport starts rendering.
2. Introduction to the Performance API
The
performanceobject provides built‑in performance parameters for front‑end monitoring.
2.1. performance.now()
performance.now()returns the number of milliseconds elapsed from
performance.navigationStartto the current moment.
performance.navigationStartmarks the earliest timestamp of the navigation.
2.2. performance.timing
2.3. performance.getEntries()
performance.getEntries()returns an array of
PerformanceEntryobjects, each containing timing information for a resource request (scripts, stylesheets, images, etc.).
Key fields include:
name : resource URL or custom mark name
startTime : request start time
duration : load time
entryType : type of entry (e.g.,
resource,
paint,
measure)
initiatorType : what initiated the request
Value
Description
mark
Object added via
mark()paint
Object added via
measure()measure
First Contentful Paint
resource
Timing for all loaded resources (most commonly used)
3. Metric Calculation Methods
3.1. First Paint and White Screen
White screen time (First Paint) is the interval from navigation start to the moment the browser begins displaying any content. It can be approximated by
performance.timing.navigationStartsubtracted from a timestamp taken before the
<body>tag.
First Paint includes any custom background rendering; it marks the first pixel painted to the screen.
First Contentful Paint (FCP) records when the browser renders the first DOM element (text, image, canvas, or SVG) to the screen.
3.2. Time to Interactive (TTI)
Google’s RAIL model defines performance thresholds for responsiveness, animation, idle time, and loading. A rough TTI estimate can be calculated as:
TTI ≈ domContentLoadedEventEnd – navigationStart
Google also provides the
tti-polyfilllibrary for more accurate measurement:
<code>import ttiPolyfill from './path/to/tti-polyfill.js';
ttiPolyfill.getFirstConsistentlyInteractive(opts).then((tti) => {
// Use `tti` value in some way.
});</code>3.3. Largest Contentful Paint (LCP)
Previously, metrics like First Meaningful Paint (FMP) and Speed Index (SI) were used, but they are complex and often inaccurate. LCP offers a simpler, more precise way to measure when the most significant content becomes visible.
The “largest paint area” refers to the element with the greatest visible area on the screen. If an element is partially off‑screen, only the visible portion counts. For images, the smaller of the rendered area and the intrinsic area is used.
LCP is captured via
PerformanceObserverlistening for
largest-contentful-paintentries. The observer records the latest entry until the user interacts with the page.
<code>const observer = new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
const lcp = lastEntry.renderTime || lastEntry.loadTime;
console.log('LCP:', lcp);
});
observer.observe({ entryTypes: ['largest-contentful-paint'] });</code>LCP can be measured using the
web-vitalslibrary:
<code>import { getLCP } from 'web-vitals';
// Measure and log the current LCP value
getLCP(console.log);</code>Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.