Web Performance Optimization: Make Websites Faster

Performance is an architectural feature, not an afterthought optimization step. Here is how to audit the critical rendering path, eliminate main-thread bottlenecks, and engineer sub-second page loads.

Mechanical stopwatch measuring precision millisecond speed
Figure 1: Millisecond latency benchmarking: measuring the user-perceived critical rendering path.

1. The Mathematics of Speed

Every 100 milliseconds of latency degrades user engagement. On mobile devices with constrained CPUs and fluctuating cellular radio connectivity, loading megabytes of uncompressed assets and blocking JavaScript bundles leads to high abandonment rates and poor search engine rankings.

Developer desk setup with performance audit metrics on screen
Figure 2: Performance profiling: analyzing frame rates and CPU flame charts in browser devtools.

2. Mastering Core Web Vitals (CWV)

Google’s Core Web Vitals evaluate real-world user experience across three essential pillars:

  • Largest Contentful Paint (LCP): Target: ≤ 2.5s. Measures perceived loading speed by marking when the largest content element (typically the hero image or main heading) is rendered to the screen.
  • Interaction to Next Paint (INP): Target: ≤ 200ms. Measures overall page responsiveness to user taps, clicks, and keystrokes throughout the entire session lifecycle.
  • Cumulative Layout Shift (CLS): Target: ≤ 0.1. Measures visual stability by calculating the sum of unexpected layout layout shifts as content streams in.

3. Modern Image Optimization: AVIF & WebP

Images frequently account for over 70% of total page weight. Modern optimization requires:

  1. Format Modernization: Converting legacy JPEG/PNG images to next-generation formats like AVIF and WebP, saving 30% to 50% in byte size at identical visual fidelity.
  2. Responsive Sources: Using the <picture> element and srcset to deliver appropriately sized images matching the user's viewport resolution.
  3. Layout Stability: Always specifying explicit width and height attributes to eliminate Cumulative Layout Shift (CLS).
<picture>
  <source type="image/avif" srcset="hero-800.avif 800w, hero-1600.avif 1600w">
  <source type="image/webp" srcset="hero-800.webp 800w, hero-1600.webp 1600w">
  <img src="hero-800.jpg" alt="Server room" width="1600" height="900" loading="eager">
</picture>
Fiber optic networking cables delivering low latency packets
Figure 3: CDN edge routing: terminating TLS sessions physically closer to the user.

4. Zero-Penalty Font Strategies

Custom typography gives websites editorial character, but poorly loaded web fonts block page rendering or cause jarring layout shifts:

  • Use font-display: swap to allow fallback fonts to paint immediately.
  • Subset your font files to include only the required Unicode character ranges (e.g., Latin basic), reducing font file sizes from 200KB down to 18KB.
  • Self-host fonts from the same origin to eliminate external DNS lookups and TLS negotiations.

5. Taming JavaScript Overhead

JavaScript is the single most expensive resource on the web. 100KB of JPEG simply decodes on the GPU, but 100KB of JavaScript must be decompressed, parsed into an Abstract Syntax Tree (AST), compiled to bytecode by V8, and executed on the single-threaded CPU main thread.

Keep bundle sizes lean by using vanilla JavaScript where feasible, splitting code dynamically with import(), and deferring non-essential scripts.

Terminal code window displaying asset build sizes and compression statistics
Figure 4: Inspecting Brotli compression ratios and asset bundle size limits in terminal builds.

6. Critical CSS Optimization

Because CSS is render-blocking, inline the minimal "Critical CSS" required to style the above-the-fold content directly inside a <style> tag in the HTML <head>. Asynchronously load the remaining non-critical stylesheet to unblock initial paint.

7. HTTP Caching Headers: Cache-Control & Immutable

The fastest network request is the one that never happens:

# For hashed static assets (e.g. style.a8f21.css):
Cache-Control: public, max-age=31536000, immutable

# For dynamic HTML documents:
Cache-Control: public, max-age=0, must-revalidate

8. Gzip vs. Brotli Compression

While Gzip has been the web standard for decades, Google’s Brotli (br) algorithm provides 15% to 25% better compression ratios on text assets (HTML, CSS, JS), resulting in faster over-the-wire transit times.

9. 10-Point Performance Checklist

  1. Enable Brotli compression on your web server / CDN.
  2. Serve modern AVIF/WebP image formats with explicit dimensions.
  3. Ensure hero image loads eagerly; lazy-load all below-the-fold images.
  4. Use font-display: swap and subset font files.
  5. Add defer to all non-critical <script> tags.
  6. Set 1-year immutable caching on versioned static assets.
  7. Deploy on a global CDN with HTTP/2 or HTTP/3 Anycast.
  8. Audit third-party tracking scripts and eliminate unused analytics.
  9. Minimize CSS specificity and strip unused selectors.
  10. Profile real-world performance using Chrome DevTools Performance panel.

10. Frequently Asked Questions

Why shouldn't I lazy-load the hero image?

Applying loading="lazy" to your primary hero image tells the browser to delay fetching the image until the layout engine calculates where it sits in the viewport, severely damaging your Largest Contentful Paint (LCP) score. Always load the hero image eagerly!

What causes high Interaction to Next Paint (INP)?

High INP is caused by long-running JavaScript execution tasks (over 50ms) occupying the browser’s main thread, preventing it from processing user clicks and painting the visual response promptly.