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 performance object provides built‑in performance parameters for front‑end monitoring.
2.1. performance.now()
performance.now()returns the number of milliseconds elapsed from performance.navigationStart to the current moment. performance.navigationStart marks the earliest timestamp of the navigation.
2.2. performance.timing
2.3. performance.getEntries()
performance.getEntries()returns an array of PerformanceEntry objects, 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.navigationStart subtracted 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-polyfill library for more accurate measurement:
import ttiPolyfill from './path/to/tti-polyfill.js';
ttiPolyfill.getFirstConsistentlyInteractive(opts).then((tti) => {
// Use `tti` value in some way.
});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 PerformanceObserver listening for largest-contentful-paint entries. The observer records the latest entry until the user interacts with the page.
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'] });LCP can be measured using the web-vitals library:
import { getLCP } from 'web-vitals';
// Measure and log the current LCP value
getLCP(console.log);Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
