TL;DR
Advanced performance optimization is CDN, smart caching, lazy loading and code splitting. These techniques can improve load time by 50-80% and improve Core Web Vitals. Here's how to implement advanced optimization in 2026.
Who this is for
- Developers optimizing website performance
- Companies wanting to improve Core Web Vitals
- Website owners with performance issues
Keyword (SEO)
performance optimization, cdn, caching, lazy loading, performance optimization
CDN (Content Delivery Network)
What is CDN?
CDN is network of geographically distributed servers that:
- Store copies of static resources
- Serve them from nearest server
- Reduce latency
- Reduce load on main server
Main CDNs:
- Cloudflare (free plan)
- Vercel Edge Network
- AWS CloudFront
- Fastly
When to use CDN?
Ideal for:
- Static files (CSS, JS, images)
- Fonts
- Videos
- Global audience
Benefits:
- 30-50% faster loading
- Better Core Web Vitals
- Lower server costs
Implementation
Vercel (automatic):
- Next.js automatically uses Edge Network
- All static files through CDN
- Zero configuration
Cloudflare:
<!-- DNS setup -->
<!-- Cloudflare automatically caches static files -->
Custom CDN:
// Set Cache-Control headers
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
Caching strategies
1. Browser Caching
Cache-Control headers:
// Static files (images, CSS, JS)
Cache-Control: public, max-age=31536000, immutable
// HTML (changes frequently)
Cache-Control: public, max-age=3600, must-revalidate
// API responses (dynamic)
Cache-Control: private, max-age=300
Implementation (Next.js):
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/static/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
];
},
};
2. Service Worker Caching
Strategies:
Cache First:
// For static resources
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
Network First:
// For dynamic data
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request).catch(() => {
return caches.match(event.request);
})
);
});
Stale While Revalidate:
// For frequently changing data
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.open('v1').then((cache) => {
return cache.match(event.request).then((response) => {
const fetchPromise = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return response || fetchPromise;
});
})
);
});
3. Server-Side Caching
Redis:
// Cache API responses
const cached = await redis.get(`api:${key}`);
if (cached) return JSON.parse(cached);
const data = await fetchData();
await redis.setex(`api:${key}`, 3600, JSON.stringify(data));
return data;
In-Memory Cache:
// Node.js memory cache
const cache = new Map();
function getCached(key) {
const cached = cache.get(key);
if (cached && cached.expires > Date.now()) {
return cached.data;
}
return null;
}
Lazy Loading
1. Images
Native lazy loading:
<img src="image.jpg" loading="lazy" alt="Description">
Intersection Observer:
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
imageObserver.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
Next.js Image:
import Image from 'next/image';
<Image
src="/image.jpg"
alt="Description"
width={800}
height={600}
loading="lazy"
placeholder="blur"
/>
2. JavaScript
Dynamic imports:
// Lazy load component
const HeavyComponent = lazy(() => import('./HeavyComponent'));
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
Code splitting:
// Webpack automatic code splitting
import('./module').then(module => {
module.doSomething();
});
3. CSS
Critical CSS:
<!-- Inline critical CSS -->
<style>
/* Above-the-fold styles */
</style>
<!-- Lazy load rest -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
Code Splitting
1. Route-based splitting
Next.js (automatic):
// Each page automatically split
// pages/about.js → about.js bundle
// pages/contact.js → contact.js bundle
React Router:
const About = lazy(() => import('./pages/About'));
const Contact = lazy(() => import('./pages/Contact'));
2. Component-based splitting
React:
const Chart = lazy(() => import('./components/Chart'));
function Dashboard() {
return (
<Suspense fallback={<div>Loading chart...</div>}>
<Chart />
</Suspense>
);
}
3. Vendor splitting
Webpack:
// Split vendor libraries
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
}
Performance monitoring
1. Core Web Vitals
Metrics:
- LCP (Largest Contentful Paint) < 2.5s
- FID (First Input Delay) < 100ms
- CLS (Cumulative Layout Shift) < 0.1
Tools:
- Google PageSpeed Insights
- Chrome DevTools Lighthouse
- Web Vitals Chrome Extension
2. Real User Monitoring (RUM)
Tools:
- Google Analytics (Core Web Vitals)
- Vercel Analytics
- New Relic Browser
- Datadog RUM
3. Synthetic Monitoring
Tools:
- Pingdom
- UptimeRobot
- StatusCake
Best practices
1. Minimize bundle size
Ways:
- Tree shaking
- Remove unused code
- Minification
- Compression (gzip, brotli)
2. Optimize images
Formats:
- WebP (best)
- AVIF (newest)
- Fallback to JPEG/PNG
Sizing:
- Responsive images (srcset)
- Proper dimensions
- Compression
3. Preload critical resources
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/hero-image.jpg" as="image">
4. Defer non-critical JavaScript
<script src="analytics.js" defer></script>
<script src="chat-widget.js" defer></script>
FAQ
What are most important performance metrics?
Core Web Vitals: LCP, FID, CLS. Additionally: TTI (Time to Interactive), FCP (First Contentful Paint), TBT (Total Blocking Time).
Is CDN always needed?
For global audience yes. For local (one country) may not be necessary, but still helps.
How often to update cache?
Depends on resource type: static files (1 year), HTML (1 hour), API (5 minutes). Use appropriate Cache-Control headers.