Web Performance Optimization Guide

Speed is a feature. Fast sites rank better, convert more visitors, and create better user experiences. Here are practical ways to make your site faster.
Optimize Your Images
Images are usually the biggest files on a web page. Optimizing them has the largest impact.
Quick Image Wins
- Use WebP format (30% smaller than JPEG)
- Compress images before uploading
- Serve appropriately sized images
In Next.js, the Image component handles much of this automatically:
import Image from 'next/image'
// Next.js optimizes automatically
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority // Load immediately for above-fold images
/>
Image Sizing Rule
Never serve a 2000px image to display at 400px. Size images to their display size (or 2x for retina).
For background images in CSS:
/* Serve different sizes based on screen */
.hero {
background-image: url('/hero-mobile.webp');
}
@media (min-width: 768px) {
.hero {
background-image: url('/hero-desktop.webp');
}
}
Lazy Load Below the Fold
Do not load everything at once. Load what users see first, defer the rest.
Above vs Below the Fold
Content visible without scrolling (above the fold) should load immediately. Everything else can wait until users scroll to it.
// Above fold - load immediately
<Image src="/hero.jpg" priority />
// Below fold - lazy load (default in Next.js)
<Image src="/feature.jpg" />
For non-Next.js projects:
<!-- Native lazy loading -->
<img src="image.jpg" loading="lazy" alt="Description" />
<!-- Lazy load iframes too -->
<iframe src="video.html" loading="lazy"></iframe>
Do Not Lazy Load Everything
Above-the-fold content should NOT be lazy loaded. It causes layout shift and hurts perceived performance.
Minimize JavaScript
Every kilobyte of JavaScript has a cost. The browser must download, parse, and execute it all.
JavaScript Cost
100KB of JavaScript is not the same as 100KB of images. JavaScript blocks rendering and requires CPU time to execute.
Ways to reduce JavaScript:
// Dynamic imports - only load when needed
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Spinner />
})
// Only render on client if needed
const ClientOnlyChart = dynamic(() => import('./Chart'), {
ssr: false
})
Bundle Analysis
Run npm run build and check your bundle sizes. Look for unexpectedly large packages.
Questions to ask:
- Do you need that entire UI library or just a few components?
- Is that date library necessary or can native Date work?
- Are you importing the whole lodash or just the functions you need?
// Bad - imports everything
import _ from 'lodash'
// Good - imports only what you need
import debounce from 'lodash/debounce'
Enable Caching
Caching lets returning visitors load your site faster by reusing files they already downloaded.
Cache-Control Headers
Set appropriate cache headers for different file types.
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/images/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
Cache duration guidelines:
| File Type | Cache Duration | Why |
|---|---|---|
| Images | 1 year | Rarely change |
| CSS/JS (hashed) | 1 year | Hash changes when content changes |
| HTML | No cache or short | Needs to be fresh |
| API responses | Varies | Depends on data freshness needs |
Core Web Vitals
Google measures these three metrics. They affect both user experience and search rankings.
The Three Vitals
- LCP (Largest Contentful Paint) - How fast main content loads
- INP (Interaction to Next Paint) - How responsive to clicks
- CLS (Cumulative Layout Shift) - How stable the layout is
Quick fixes for each:
LCP - Target under 2.5 seconds:
- Optimize your largest image
- Use
priorityon hero images - Reduce server response time
INP - Target under 200ms:
- Break up long JavaScript tasks
- Reduce third-party scripts
- Use web workers for heavy computation
CLS - Target under 0.1:
/* Always set dimensions to prevent layout shift */
img, video {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
Font Loading CLS
Fonts loading late cause text to reflow. Use font-display: swap and preload critical fonts.
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
Performance Testing
Measure before and after every optimization.
Free Tools
- Chrome DevTools Lighthouse
- PageSpeed Insights (web)
- WebPageTest (detailed analysis)
Run tests on:
- Your slowest pages
- Pages with the most traffic
- Key conversion pages
Test on throttled connections and mid-range devices, not just your fast development machine.
Key Takeaways
Performance optimization priorities:
- Optimize images (biggest impact for most sites)
- Lazy load below-the-fold content
- Audit and reduce JavaScript bundles
- Set appropriate cache headers
- Monitor Core Web Vitals
Small improvements compound. A 100ms improvement might not seem like much, but users notice when every interaction feels snappier.