Performance Optimization: Speed Matters
Practical techniques for faster, more responsive websites
Website performance directly impacts user experience, SEO rankings, and conversion rates. A one-second delay in page load time can reduce conversions by 7%. Let's explore practical optimization techniques that deliver measurable results.
Lighthouse Audits: Your Performance Baseline
Google's Lighthouse provides a comprehensive performance audit accessible through Chrome DevTools. Focus on these key metrics:
- First Contentful Paint (FCP): Time until first content renders (target: under 1.8s)
- Largest Contentful Paint (LCP): Time for main content to load (target: under 2.5s)
- Time to Interactive (TTI): When page becomes fully interactive (target: under 3.8s)
- Cumulative Layout Shift (CLS): Visual stability score (target: under 0.1)
Run audits regularly and track improvements over time. Use both mobile and desktop modes—mobile performance often reveals hidden issues.
Image Optimization: Low-Hanging Fruit
Images typically account for 50% or more of page weight. Optimize them aggressively:
Modern Formats:
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Description">
</picture>
Responsive Images:
<img
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
src="medium.jpg"
alt="Description"
>
Key strategies:
- Use WebP format with JPEG fallback
- Compress images (tools: TinyPNG, ImageOptim, Squoosh)
- Serve appropriately sized images for viewport
- Add explicit width and height attributes to prevent layout shift
Lazy Loading: Load What's Needed
Don't load resources until they're needed. Native lazy loading is now widely supported:
<img src="image.jpg" loading="lazy" alt="Description">
<iframe src="video.html" loading="lazy"></iframe>
For JavaScript-heavy components, use dynamic imports:
// React example
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
Code Splitting: Break Up Large Bundles
Instead of serving one massive JavaScript bundle, split code by route or feature:
Route-based splitting:
// React Router example
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
Webpack automatically splits:
// Dynamic import creates separate chunk
button.addEventListener('click', async () => {
const module = await import('./heavyModule.js');
module.doSomething();
});
Critical CSS: Eliminate Render-Blocking
Inline critical above-the-fold CSS and defer the rest:
<head>
<style>
/* Critical CSS inlined here */
.header { /* styles */ }
</style>
<link rel="preload" href="styles.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
Tools like Critical or Penthouse extract critical CSS automatically.
Caching Strategies
Leverage browser caching and CDNs:
# .htaccess example
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
Font Optimization
Web fonts can block rendering. Optimize their delivery:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"
rel="stylesheet">
Use font-display: swap to show fallback fonts
immediately:
@font-face {
font-family: 'CustomFont';
src: url('font.woff2') format('woff2');
font-display: swap;
}
Minification and Compression
- Minify: Remove whitespace from HTML, CSS, JavaScript
- Gzip/Brotli: Enable server-side compression (60-80% size reduction)
- Tree shaking: Remove unused code from final bundles
Third-Party Scripts
External scripts often impact performance significantly:
- Audit all third-party scripts—remove unnecessary ones
- Load analytics and tracking scripts asynchronously
-
Use
deferorasyncattributes - Consider self-hosting critical scripts
Performance Budget
Set and enforce limits:
- Total page size: under 1.5MB
- JavaScript bundle: under 300KB
- Number of requests: under 50
- LCP: under 2.5 seconds
Use tools like Bundlesize or Lighthouse CI to fail builds that exceed your budget.
Performance optimization is an ongoing process, not a one-time task. Regular audits, monitoring, and incremental improvements keep your site fast as it evolves.