Web Performance Optimization: Speed Up Your Site

ยท 12 min read

Core Web Vitals Explained

Core Web Vitals are Google's key metrics for measuring user experience. They directly impact your search rankings and should be the foundation of any performance optimization effort.

LCP โ€” Largest Contentful Paint

Target: under 2.5 seconds. LCP measures when the largest visible content element (hero image, heading, or video) finishes rendering. To improve LCP:

INP โ€” Interaction to Next Paint

Target: under 200 milliseconds. INP measures responsiveness โ€” how quickly the page responds to user interactions (clicks, taps, key presses). To improve INP:

CLS โ€” Cumulative Layout Shift

Target: under 0.1. CLS measures visual stability โ€” how much the page layout shifts unexpectedly during loading. To improve CLS:

Image Optimization

Images typically account for 50-70% of a page's total weight. Optimizing them is the single biggest performance win for most sites.

Choose the Right Format

Format Best For Compression
WebPPhotos, complex graphics25-35% smaller than JPEG
AVIFPhotos (best compression)50% smaller than JPEG
SVGIcons, logos, illustrationsScales infinitely, tiny files
PNGTransparency needed, screenshotsLossless, larger files

Responsive Images

<!-- Serve different sizes based on viewport -->
<picture>
  <source srcset="hero-800.avif 800w, hero-1200.avif 1200w, hero-1600.avif 1600w"
          type="image/avif" sizes="100vw">
  <source srcset="hero-800.webp 800w, hero-1200.webp 1200w, hero-1600.webp 1600w"
          type="image/webp" sizes="100vw">
  <img src="hero-1200.jpg" alt="Hero image"
       width="1200" height="600"
       loading="lazy" decoding="async">
</picture>

Compression Commands

# Convert to WebP (cwebp)
cwebp -q 80 input.png -o output.webp

# Convert to AVIF (avifenc)
avifenc --min 20 --max 35 input.png output.avif

# Optimize JPEG (jpegoptim)
jpegoptim --strip-all --max=85 *.jpg

# Optimize PNG (pngquant)
pngquant --quality=65-80 --strip input.png

โšก Performance & optimization tools

Code Formatter โ†’ HTML Entity Encoder โ†’ SSL Checker โ†’

Lazy Loading

Lazy loading defers the loading of off-screen resources until the user scrolls near them. This dramatically reduces initial page load time.

Native Lazy Loading

<!-- Images: add loading="lazy" -->
<img src="photo.webp" alt="Description"
     width="800" height="400"
     loading="lazy" decoding="async">

<!-- Iframes: also supports lazy loading -->
<iframe src="https://youtube.com/embed/..." loading="lazy"></iframe>

Important: Don't lazy-load above-the-fold images (especially your LCP element). Only lazy-load images below the fold.

JavaScript Intersection Observer

// Custom lazy loading with Intersection Observer
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      img.classList.add('loaded');
      observer.unobserve(img);
    }
  });
}, {
  rootMargin: '200px' // Start loading 200px before visible
});

document.querySelectorAll('img[data-src]').forEach(img => {
  observer.observe(img);
});

Code Minification

Minification removes whitespace, comments, and shortens variable names without changing functionality. It typically reduces file sizes by 30-60%.

CSS Minification

/* Before: 847 bytes */
.card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  /* Card shadow for depth */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* After minification: 156 bytes (-82%) */
.card{display:flex;flex-direction:column;padding:1.5rem;border:1px solid #e2e8f0;border-radius:.5rem;box-shadow:0 1px 3px rgba(0,0,0,.1)}

JavaScript Minification

# Using terser (recommended)
npx terser app.js -o app.min.js --compress --mangle

# Using esbuild (fastest)
npx esbuild app.js --bundle --minify --outfile=app.min.js

# Build tool integration (Vite example)
# vite.config.js
export default {
  build: {
    minify: 'terser', // or 'esbuild' (default, faster)
    terserOptions: {
      compress: { drop_console: true }
    }
  }
}

Use our Code Formatter during development to keep code readable, then minify for production. Our HTML Entity Encoder helps encode special characters that might break minification.

Caching Strategies

Effective caching can eliminate redundant network requests entirely, making return visits nearly instant.

HTTP Cache Headers

# Nginx caching configuration

# Static assets: cache for 1 year (immutable)
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# HTML: short cache, always revalidate
location ~* \.html$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

# API responses: no cache
location /api/ {
    add_header Cache-Control "no-store, no-cache, must-revalidate";
}

Cache-Busting with Hashed Filenames

<!-- Instead of: -->
<link rel="stylesheet" href="/css/style.css">

<!-- Use hashed filenames: -->
<link rel="stylesheet" href="/css/style.a3f8b2c1.css">

<!-- Build tools (Vite, Webpack) do this automatically -->

Service Worker Caching

// sw.js - Cache-first strategy for assets
self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image' ||
      event.request.url.includes('/css/') ||
      event.request.url.includes('/js/')) {
    event.respondWith(
      caches.match(event.request).then(cached => {
        return cached || fetch(event.request).then(response => {
          const clone = response.clone();
          caches.open('assets-v1').then(cache => {
            cache.put(event.request, clone);
          });
          return response;
        });
      })
    );
  }
});

CDN Configuration

A Content Delivery Network serves your content from servers closest to the user, reducing latency by 50-80% for global audiences.

Cloudflare Setup (Most Popular)

  1. Add your domain to Cloudflare
  2. Update nameservers at your registrar
  3. Enable these optimizations in the dashboard:
    • Auto Minify โ€” CSS, JavaScript, HTML
    • Brotli compression โ€” 15-20% smaller than gzip
    • HTTP/3 โ€” faster connections
    • Early Hints (103) โ€” preload critical resources
    • Polish โ€” automatic image optimization

Verify your site's SSL configuration with our SSL Checker to ensure HTTPS is properly set up โ€” this is critical for both security and performance (HTTP/2 and HTTP/3 require HTTPS).

Preconnect and DNS Prefetch

<!-- Preconnect to critical third-party origins -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

<!-- DNS prefetch for less critical resources -->
<link rel="dns-prefetch" href="https://analytics.example.com">

Critical Rendering Path

The Critical Rendering Path is the sequence of steps the browser takes to convert HTML, CSS, and JavaScript into pixels on screen. Optimizing it reduces time to first render.

Eliminate Render-Blocking Resources

<!-- Bad: blocks rendering -->
<link rel="stylesheet" href="/css/all-styles.css">
<script src="/js/app.js"></script>

<!-- Good: inline critical CSS, defer the rest -->
<style>
  /* Critical above-the-fold CSS inlined here */
  body { margin: 0; font-family: system-ui; }
  .header { display: flex; padding: 1rem; }
</style>
<link rel="stylesheet" href="/css/all-styles.css" media="print"
      onload="this.media='all'">

<!-- Defer non-critical JavaScript -->
<script src="/js/app.js" defer></script>
<script src="/js/analytics.js" async></script>

Resource Hints

<head>
  <!-- Preload critical resources -->
  <link rel="preload" as="font" href="/fonts/inter.woff2"
        type="font/woff2" crossorigin>
  <link rel="preload" as="image" href="/img/hero.webp">

  <!-- Prefetch next-page resources -->
  <link rel="prefetch" href="/about.html">

  <!-- Prerender likely next navigation -->
  <link rel="prerender" href="/pricing.html">
</head>

Performance Audit Checklist

Run through this checklist before every deployment:

Measurement Tools

Frequently Asked Questions

What is a good Lighthouse performance score?

Aim for 90+ on desktop and 80+ on mobile. A score of 50-89 needs improvement, and below 50 is poor. Focus on Core Web Vitals (LCP, INP, CLS) as they have the most impact on user experience and SEO.

Does web performance affect SEO?

Yes. Google uses Core Web Vitals as ranking signals. Poor performance leads to higher bounce rates and lower engagement, which indirectly affects rankings further. Fast sites consistently outrank slow ones for similar content quality.

Should I use WebP or AVIF for images?

Use both with the <picture> element for maximum compatibility. AVIF offers the best compression (50% smaller than JPEG) but slower to encode. WebP is widely supported and 25-35% smaller than JPEG. Serve AVIF first with WebP fallback.

How do I find what's slowing down my website?

Start with Chrome DevTools: open the Performance tab, record a page load, and look at the waterfall chart. The Network tab shows which resources are largest and slowest. Run Lighthouse for specific recommendations. Use WebPageTest.org for detailed analysis including TTFB, render timing, and third-party impact.

Related Tools

Code Formatter HTML Entity Encoder SSL Checker CSS Minifier JSON Formatter