Optimizing website performance in 2026

In short: As of September 5, 2026, measure Core Web Vitals in the field first, then fix the dominant cause: a late main resource for LCP, blocking JavaScript for INP, or unreserved space for CLS. My recommendation is to start with PageSpeed Insights, confirm the diagnosis in Chrome DevTools, and optimize images and the critical rendering path before adding complex tooling.
Web performance should be driven by measurements, not by applying a random checklist of tips. Core Web Vitals provide a shared framework for connecting loading, responsiveness, and stability to your users’ real experience.
Which Core Web Vitals should you monitor?
Google measures three key metrics that reflect the user’s perception of speed:
| Metric | What it measures | “Good” threshold |
|---|---|---|
| LCP (Largest Contentful Paint) | Loading time of the largest visible element | < 2.5 seconds |
| INP (Interaction to Next Paint) | Response time to user interactions | < 200 ms |
| CLS (Cumulative Layout Shift) | Visual stability of the page | < 0.1 |
INP replaced FID (First Input Delay) as the interactivity metric. FID observed only the delay of the first interaction, while INP evaluates responsiveness across the entire visit.
How do you optimize LCP?
Improving LCP often requires examining the entire loading chain: server response, discovery of the main resource, download, and rendering.
Image optimization
Images often represent the heaviest part of a page:
<!-- Use modern formats -->
<picture>
<source srcset="hero.avif" type="image/avif" />
<source srcset="hero.webp" type="image/webp" />
<img
src="hero.jpg"
alt="Description"
width="1200"
height="600"
loading="eager"
fetchpriority="high"
/>
</picture>
<!-- Responsive images with srcset -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, 800px"
alt="Description"
width="800"
height="600"
/>
AVIF and WebP can reduce image weight compared with JPEG. The actual gain depends on the content, encoder, and selected quality level, so compare files using your own images.
Preload critical resources
Tell the browser to prioritize loading resources essential to initial rendering:
<!-- Preload the LCP image -->
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high" />
<!-- Preload critical fonts -->
<link rel="preload" as="font" href="/fonts/inter-var.woff2" type="font/woff2" crossorigin />
<!-- Inline critical CSS -->
<style>
/* Minimal CSS for initial render */
.hero {
/* essential styles */
}
</style>
Reduce TTFB (Time to First Byte)
TTFB directly impacts LCP. Key optimizations:
- Use a CDN to serve content from a geographically close server
- Implement server-side caching (Varnish, Redis, or native CMS cache)
- Optimize database queries (indexes, N+1 queries)
- Use performant hosting with HTTP/2 or HTTP/3
How do you improve INP?
INP measures how quickly your site produces visual feedback after an interaction such as a click, tap, or key press. Long JavaScript tasks block the main thread and degrade this responsiveness.
Break up long tasks
// Bad: monolithic blocking task
function processData(items) {
items.forEach((item) => heavyComputation(item));
}
// Good: splitting with scheduler.yield()
async function processData(items) {
for (const item of items) {
heavyComputation(item);
// Yield control to the browser
if (navigator.scheduling?.isInputPending()) {
await scheduler.yield();
}
}
}
Debounce and throttle handlers
// Debounce for search inputs
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
input.addEventListener('input', debounce(handleSearch, 300));
Defer non-critical JavaScript
<!-- Non-essential scripts deferred -->
<script src="analytics.js" defer></script>
<script src="chat-widget.js" async></script>
<!-- Dynamic loading -->
<script type="module">
if (userNeedsFeature) {
import('./feature.js');
}
</script>
How do you reduce CLS?
CLS measures unexpected layout shifts that disrupt the user experience.
Always set media dimensions
<!-- Always specify width and height -->
<img src="photo.jpg" alt="Description" width="800" height="600" />
<!-- Or via CSS with aspect-ratio -->
<style>
.image-container {
aspect-ratio: 4 / 3;
width: 100%;
}
</style>
Reserve space for dynamic content
/* Space reserved for ads */
.ad-slot {
min-height: 250px;
width: 300px;
}
/* Space reserved for AJAX-loaded content */
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
animation: shimmer 1.5s infinite;
min-height: 100px;
}
When should you use lazy loading?
Lazy loading defers loading of non-visible resources:
<!-- Native lazy loading for images and iframes -->
<img src="photo.jpg" loading="lazy" alt="Description" />
<iframe src="video.html" loading="lazy"></iframe>
<!-- IMPORTANT: never lazy load the LCP image -->
<img src="hero.jpg" loading="eager" fetchpriority="high" alt="Hero" />
JavaScript for finer control:
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
},
{ rootMargin: '200px' },
);
document.querySelectorAll('img[data-src]').forEach((img) => {
observer.observe(img);
});
Which caching strategies should you apply?
Cache is your best ally for repeat visits:
HTTP cache
# Nginx configuration for static caching
location ~* \.(css|js|jpg|jpeg|png|webp|avif|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML with validation
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
Service Worker for offline caching
// sw.js - Cache static resources
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('static-v1').then((cache) => {
return cache.addAll(['/', '/styles.css', '/app.js', '/fonts/inter-var.woff2']);
}),
);
});
When does a CDN improve performance?
A CDN (Content Delivery Network) distributes resources from servers close to your users. Different services address different needs:
- Cloudflare: CDN network with integrated security services
- Fastly: programmable CDN designed for applications
- AWS CloudFront: integration with the AWS ecosystem
- Bunny CDN: accessible setup for content delivery
A CDN reduces TTFB and improves LCP for users far from your origin server.
How do you measure and monitor performance?
Optimization is a continuous process. Field data shows what your users experience, while lab tools help explain why. Useful tools include:
- Google PageSpeed Insights: CrUX field data and Lighthouse diagnostics
- Chrome DevTools (Performance panel): local analysis of networking, rendering, and interactions
- Lighthouse: reproducible lab audits
- web-vitals: metric collection from your users
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToAnalytics(metric) {
navigator.sendBeacon('/analytics', JSON.stringify(metric));
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
Conclusion
Web performance optimization follows a simple loop: measure in the field, diagnose in the lab, fix, and monitor. Start with the LCP resource and critical rendering path, limit JavaScript work that delays interactions, and then stabilize the layout. Image, cache, and CDN optimizations support these priorities; they do not replace them.
Sources
Frequently asked questions
What are the three Core Web Vitals?
The three Core Web Vitals are LCP for main-content loading speed, INP for responsiveness, and CLS for visual stability. Evaluate them with real-user data, supplemented by lab tests.
How do you improve a website's LCP?
Make the LCP resource discoverable in the initial HTML, do not lazy-load it, and give it high priority when needed. Also reduce TTFB, resource weight, and render delay.
Which tool should you use to measure Core Web Vitals?
Start with PageSpeed Insights to compare CrUX field data with lab diagnostics. Then use Chrome DevTools to investigate the network, rendering, and interactions in detail.
Is Lighthouse enough to measure real-world performance?
No. Lighthouse is a useful lab diagnostic tool, but it does not replace field data collected from your users.