Website Performance Optimization
The complete guide to optimizing your website performance. From Core Web Vitals to image optimization and caching - everything with practical code examples.
Why website performance is crucial
Website performance has been an official Google ranking factor since 2021. With the introduction of Core Web Vitals, Google has defined clear metrics that make user experience measurable. Slow websites not only lose rankings, but also visitors and revenue.
In competitive digital markets, performance can make the difference between success and failure. A fast website is not only SEO-relevant, but directly revenue-relevant.
Largest Contentful Paint (LCP)
LCP measures how long it takes for the largest visible content element in the viewport to load. This is often a hero image, large heading, or video. Google recommends an LCP under 2.5 seconds.
Benchmarks
Optimization measures
1. Optimize server response time
TTFB (Time to First Byte) should be under 600ms. We recommend fast hosting providers for optimal server response times.
# Nginx Performance Tuning
worker_processes auto;
worker_connections 4096;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss;
# Caching
proxy_cache_path /var/cache/nginx levels=1:2
keys_zone=my_cache:10m max_size=1g
inactive=60m use_temp_path=off; 2. Prioritize resources with preload
Critical resources like hero images or important fonts should be preloaded.
<!-- Preload critical resources -->
<link rel="preload" as="image" href="/hero-image.webp"
type="image/webp" fetchpriority="high">
<link rel="preload" as="font" href="/fonts/main.woff2"
type="font/woff2" crossorigin>
<!-- Preconnect to external domains -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://analytics.google.com"> 3. Deliver images optimally
Use modern image formats (WebP, AVIF) and responsive images with srcset.
<picture>
<!-- AVIF for modern browsers -->
<source type="image/avif"
srcset="hero-400.avif 400w,
hero-800.avif 800w,
hero-1200.avif 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px">
<!-- WebP Fallback -->
<source type="image/webp"
srcset="hero-400.webp 400w,
hero-800.webp 800w,
hero-1200.webp 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px">
<!-- JPEG Fallback -->
<img src="hero-800.jpg"
alt="Hero Image"
loading="eager"
fetchpriority="high"
width="1200"
height="600">
</picture> First Input Delay (FID) / Interaction to Next Paint (INP)
Update 2024: Google is replacing FID with INP (Interaction to Next Paint) in March 2024. INP measures response time to all user interactions, not just the first.
FID/INP measures the time between the first user interaction (click, tap) and the browser response. A good FID is under 100ms, a good INP under 200ms.
Optimization measures
1. Reduce JavaScript execution
Large JavaScript code blocks the main thread. Code splitting and lazy loading are essential.
// Dynamic Imports for code splitting
const HeavyComponent = lazy(() => import('./HeavyComponent'));
// React.lazy with Suspense
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
// Webpack Magic Comments for chunk names
import(/* webpackChunkName: "analytics" */ './analytics'); 2. Avoid long tasks
Tasks over 50ms block user interactions. Use Web Workers for compute-intensive operations.
// Main Thread
const worker = new Worker('heavy-calculation.js');
worker.postMessage({ data: largeDataset });
worker.onmessage = (e) => {
updateUI(e.data);
};
// heavy-calculation.js (Worker)
self.onmessage = (e) => {
const result = performHeavyCalculation(e.data);
self.postMessage(result);
}; 3. Optimize third-party scripts
Analytics, chatbots and other third-party scripts should be loaded async or with defer.
<!-- Load asynchronously -->
<script async src="https://www.googletagmanager.com/gtag/js"></script>
<!-- With defer for better timing -->
<script defer src="/analytics.js"></script>
<!-- Self-hosted instead of CDN for better performance -->
<script defer src="/libs/jquery.min.js"></script> Cumulative Layout Shift (CLS)
CLS measures the visual stability of a page. When elements "jump" during loading, it leads to poor user experience. A good CLS is under 0.1.
Common CLS causes
Browser doesn't know the size and reserves no space
Content appears after initial rendering
FOIT (Flash of Invisible Text) shifts layout
Solutions
1. Always specify width and height
<!-- Explicit dimensions -->
<img src="logo.png" alt="Logo" width="200" height="50">
<!-- Or aspect-ratio in CSS -->
<img src="hero.jpg" alt="Hero" style="aspect-ratio: 16/9; width: 100%;">
<!-- Modern with CSS aspect-ratio -->
.hero-image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
} 2. Reserve space for dynamic content
<!-- Skeleton screen for ads -->
.ad-placeholder {
width: 100%;
height: 250px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
} 3. Optimize font loading
/* font-display for better fallback */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap; /* Shows fallback immediately */
font-weight: 400;
font-style: normal;
}
/* Preload critical fonts */
<link rel="preload" as="font"
href="/fonts/custom.woff2"
type="font/woff2"
crossorigin> Image optimization
Images often account for 50-70% of total page size. Optimization is the biggest performance lever.
Format comparison
| Format | Browser support | File size | Recommendation |
|---|---|---|---|
| AVIF | ~85% | Smallest | First choice for modern browsers |
| WebP | ~96% | 30% smaller than JPEG | Best fallback |
| JPEG | 100% | Baseline | Legacy support |
| PNG | 100% | Largest | Only for transparency |
Optimization tools
Sharp (Node.js)
const sharp = require('sharp');
// Convert image to multiple formats
await sharp('input.jpg')
.resize(1200, 800, { fit: 'cover' })
.webp({ quality: 80 })
.toFile('output-1200.webp');
await sharp('input.jpg')
.resize(1200, 800, { fit: 'cover' })
.avif({ quality: 70 })
.toFile('output-1200.avif'); Squoosh CLI
# Installation
npm install -g @squoosh/cli
# Batch conversion to WebP
squoosh-cli --webp '{"quality":80}' images/*.jpg
# To AVIF with different sizes
squoosh-cli --avif '{"quality":70}' \
--resize '{"width":1200}' \
--resize '{"width":800}' \
--resize '{"width":400}' \
images/*.jpg Caching strategies
Effective caching reduces server load and massively improves performance for returning visitors.
Browser caching (.htaccess)
<IfModule mod_expires.c>
ExpiresActive On
# Images - 1 year
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# CSS and JS - 1 month
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Fonts - 1 year
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# HTML - 1 hour
ExpiresByType text/html "access plus 1 hour"
</IfModule> Service Worker caching
// service-worker.js
const CACHE_NAME = 'v1';
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png'
];
// Install Event - Cache resources
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(urlsToCache))
);
});
// Fetch Event - Cache-First Strategy
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => {
// Cache hit - return cached response
if (response) return response;
// Fetch from network
return fetch(event.request);
})
);
}); CDN & Edge Computing
A Content Delivery Network (CDN) distributes your content across servers worldwide and delivers it from the geographically nearest location. We recommend CDNs with strong presence in your target regions.
Cloudflare
- Free plan available
- DDoS protection included
- Edge Functions for SSR
BunnyCDN
- Very affordable ($1/TB)
- Best performance in Europe
- Image optimization included
Hosting recommendations
For optimal performance, we recommend hosting providers with servers in your target region or with global CDN coverage.
Hetzner
Servers in Germany (Nuremberg & Falkenstein)
- • Best performance/price ratio in Germany
- • 20 TB traffic included
- • Very low latency in Europe (<10ms)
DigitalOcean
Global datacenters (Frankfurt, London, NYC)
- • Developer-friendly platform
- • Managed databases and Kubernetes
- • Easy scaling and backups
Vercel / Netlify
Edge network (global CDN)
- • Perfect for Jamstack (Astro, Next.js, etc.)
- • Automatic deployments via Git
- • Global CDN included
Professional performance optimization
Let us analyze your website and bring it to top performance. We optimize Core Web Vitals, reduce load times, and increase your conversion rate.