Website Speed Optimization Techniques - Complete Guide
Published: September 25, 2024 | Reading time: 25 minutes
Website Speed Optimization Overview
Website speed optimization improves user experience and search rankings:
Speed Optimization Benefits
# Speed Optimization Benefits
- Improved user experience
- Better search rankings
- Higher conversion rates
- Reduced bounce rates
- Mobile performance
- Core Web Vitals compliance
- SEO advantages
Core Web Vitals
Google's Core Web Vitals
Core Web Vitals Metrics
- LCP (Largest Contentful Paint)
- FID (First Input Delay)
- CLS (Cumulative Layout Shift)
- FCP (First Contentful Paint)
- TTI (Time to Interactive)
Performance Thresholds
- LCP: < 2.5 seconds
- FID: < 100 milliseconds
- CLS: < 0.1
- FCP: < 1.8 seconds
- TTI: < 3.8 seconds
Image Optimization
Image Compression Techniques
Image Optimization Implementation
# Image Optimization Script
#!/bin/bash
# image-optimizer.sh
# Configuration
INPUT_DIR="/var/www/images"
OUTPUT_DIR="/var/www/images/optimized"
QUALITY=85
MAX_WIDTH=1920
# Create output directory
mkdir -p $OUTPUT_DIR
# Optimize JPEG images
find $INPUT_DIR -name "*.jpg" -o -name "*.jpeg" | while read file; do
filename=$(basename "$file")
echo "Optimizing $filename..."
# Resize and compress
convert "$file" \
-resize "${MAX_WIDTH}x>" \
-quality $QUALITY \
-strip \
-interlace Plane \
"$OUTPUT_DIR/$filename"
done
# Optimize PNG images
find $INPUT_DIR -name "*.png" | while read file; do
filename=$(basename "$file")
echo "Optimizing $filename..."
# Compress PNG
pngquant --quality=65-80 --ext .png --force "$file"
# Move optimized file
mv "${file%.*}-fs8.png" "$OUTPUT_DIR/$filename"
done
# Generate WebP versions
find $INPUT_DIR -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" | while read file; do
filename=$(basename "$file" | sed 's/\.[^.]*$//')
echo "Generating WebP for $filename..."
cwebp -q $QUALITY "$file" -o "$OUTPUT_DIR/${filename}.webp"
done
# HTML Implementation
# Responsive images with WebP fallback
# CSS Implementation
# Responsive images
.responsive-image {
max-width: 100%;
height: auto;
display: block;
}
# Lazy loading implementation
img[loading="lazy"] {
opacity: 0;
transition: opacity 0.3s;
}
img[loading="lazy"].loaded {
opacity: 1;
}
CSS Optimization
CSS Performance Techniques
CSS Optimization Strategies
# CSS Optimization Techniques
# 1. Critical CSS Inlining
# Extract critical CSS for above-the-fold content
const critical = require('critical');
critical.generate({
inline: true,
base: 'dist/',
src: 'index.html',
dest: 'index.html',
width: 1300,
height: 900,
minify: true
});
# 2. CSS Minification
# Using PostCSS with plugins
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano')({
preset: 'default',
}),
require('postcss-combine-duplicated-selectors'),
require('postcss-combine-media-query')
]
}
# 3. CSS Purging
# Remove unused CSS
const purgecss = require('@fullhuman/postcss-purgecss');
module.exports = {
plugins: [
purgecss({
content: ['./src/**/*.html', './src/**/*.js'],
defaultExtractor: content => content.match(/[\w-/:]+(?
# Load non-critical CSS asynchronously
# 5. CSS Architecture
# Use CSS custom properties for theming
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--font-size-base: 1rem;
--line-height-base: 1.5;
}
.button {
background-color: var(--primary-color);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
}
# 6. CSS Performance Best Practices
# Avoid expensive selectors
/* Bad */
div > ul > li > a { }
/* Good */
.nav-link { }
# Use efficient selectors
/* Bad */
* { margin: 0; }
/* Good */
body, h1, h2, h3, p { margin: 0; }
# Minimize reflows and repaints
.element {
transform: translateX(100px); /* Use transform instead of left */
opacity: 0.5; /* Use opacity instead of visibility */
}
JavaScript Optimization
JavaScript Performance Techniques
JavaScript Optimization Strategies
# JavaScript Optimization Techniques
# 1. Code Splitting
# Webpack configuration
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
# Dynamic imports
// Lazy load components
const loadComponent = async () => {
const { default: Component } = await import('./Component.js');
return Component;
};
// Route-based code splitting
const routes = [
{
path: '/',
component: () => import('./pages/Home.js')
},
{
path: '/about',
component: () => import('./pages/About.js')
}
];
# 2. Bundle Optimization
# Tree shaking configuration
module.exports = {
mode: 'production',
optimization: {
usedExports: true,
sideEffects: false
}
};
# 3. JavaScript Performance Best Practices
# Debouncing and throttling
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
# 4. Memory Management
# Avoid memory leaks
class Component {
constructor() {
this.elements = [];
this.setupEventListeners();
}
setupEventListeners() {
document.addEventListener('click', this.handleClick.bind(this));
}
destroy() {
// Clean up event listeners
document.removeEventListener('click', this.handleClick.bind(this));
this.elements = null;
}
}
# 5. Async/Await Optimization
# Efficient async operations
async function fetchData() {
try {
const [users, posts, comments] = await Promise.all([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments')
]);
return {
users: await users.json(),
posts: await posts.json(),
comments: await comments.json()
};
} catch (error) {
console.error('Error fetching data:', error);
}
}
Server-Side Optimization
Backend Performance Techniques
Server-Side Optimization
# Server-Side Optimization Techniques
# 1. HTTP/2 Configuration
# Nginx HTTP/2 setup
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# HTTP/2 push
location / {
http2_push /css/style.css;
http2_push /js/app.js;
}
}
# 2. Compression Configuration
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Brotli compression
brotli on;
brotli_comp_level 6;
brotli_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript;
# 3. Caching Headers
# Static assets caching
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
# HTML caching
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# 4. Database Optimization
# Connection pooling
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
host: 'localhost',
user: 'user',
password: 'password',
database: 'database',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
acquireTimeout: 60000,
timeout: 60000
});
# Query optimization
// Use prepared statements
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ? AND status = ?',
[userId, 'active']
);
// Use indexes
CREATE INDEX idx_user_status ON users(status);
CREATE INDEX idx_user_email ON users(email);
# 5. API Response Optimization
# Response compression middleware
const compression = require('compression');
app.use(compression());
# Response caching
const redis = require('redis');
const client = redis.createClient();
app.get('/api/data', async (req, res) => {
const cacheKey = `data:${req.query.id}`;
try {
// Check cache first
const cached = await client.get(cacheKey);
if (cached) {
return res.json(JSON.parse(cached));
}
// Fetch from database
const data = await fetchDataFromDB(req.query.id);
// Cache for 1 hour
await client.setex(cacheKey, 3600, JSON.stringify(data));
res.json(data);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
Performance Monitoring
Performance Monitoring Setup
Performance Monitoring Implementation
# Performance Monitoring Setup
# 1. Web Vitals Monitoring
# Google Analytics 4 with Core Web Vitals
gtag('config', 'GA_MEASUREMENT_ID', {
custom_map: {
'custom_parameter_1': 'web_vitals'
}
});
# Web Vitals measurement
import {getCLS, getFID, getFCP, getLCP, getTTFB} from 'web-vitals';
function sendToAnalytics(metric) {
gtag('event', metric.name, {
event_category: 'Web Vitals',
event_label: metric.id,
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
non_interaction: true,
});
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
# 2. Performance Observer API
# Monitor performance metrics
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.duration);
// Send to analytics
if (entry.entryType === 'navigation') {
sendToAnalytics({
name: 'TTFB',
value: entry.responseStart - entry.requestStart
});
}
}
});
observer.observe({entryTypes: ['navigation', 'paint', 'largest-contentful-paint']});
# 3. Real User Monitoring (RUM)
# Custom performance monitoring
class PerformanceMonitor {
constructor() {
this.metrics = {};
this.init();
}
init() {
// Monitor page load time
window.addEventListener('load', () => {
this.metrics.pageLoadTime = performance.now();
this.sendMetrics();
});
// Monitor resource loading
this.monitorResources();
// Monitor user interactions
this.monitorInteractions();
}
monitorResources() {
const resources = performance.getEntriesByType('resource');
resources.forEach(resource => {
if (resource.duration > 1000) { // Resources taking more than 1 second
this.metrics.slowResources = this.metrics.slowResources || [];
this.metrics.slowResources.push({
name: resource.name,
duration: resource.duration
});
}
});
}
monitorInteractions() {
let interactionCount = 0;
const startTime = performance.now();
['click', 'keydown', 'scroll'].forEach(eventType => {
document.addEventListener(eventType, () => {
interactionCount++;
if (interactionCount === 1) {
this.metrics.firstInteraction = performance.now() - startTime;
}
});
});
}
sendMetrics() {
// Send to analytics service
fetch('/api/performance', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.metrics)
});
}
}
new PerformanceMonitor();
# 4. Lighthouse CI Integration
# Automated performance testing
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
numberOfRuns: 3
},
assert: {
assertions: {
'categories:performance': ['error', {minScore: 0.9}],
'categories:accessibility': ['error', {minScore: 0.9}],
'categories:best-practices': ['error', {minScore: 0.9}],
'categories:seo': ['error', {minScore: 0.9}]
}
},
upload: {
target: 'temporary-public-storage'
}
}
};
Mobile Optimization
Mobile Performance Techniques
Mobile Optimization Strategies
# Mobile Optimization Techniques
# 1. Responsive Images
# Picture element with multiple sources
# 2. Touch Optimization
# Touch-friendly interfaces
.touch-target {
min-height: 44px;
min-width: 44px;
padding: 12px;
}
# Prevent zoom on input focus
input, select, textarea {
font-size: 16px;
}
# 3. Mobile-First CSS
# Mobile-first approach
.container {
width: 100%;
padding: 1rem;
}
@media (min-width: 768px) {
.container {
max-width: 750px;
margin: 0 auto;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1200px;
}
}
# 4. Progressive Web App (PWA)
# Service Worker for caching
const CACHE_NAME = 'app-cache-v1';
const urlsToCache = [
'/',
'/css/style.css',
'/js/app.js',
'/images/logo.png'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
# 5. Mobile Performance Best Practices
# Reduce JavaScript execution
// Use requestIdleCallback for non-critical tasks
function processData() {
// Heavy computation
}
if ('requestIdleCallback' in window) {
requestIdleCallback(processData);
} else {
setTimeout(processData, 1);
}
# Optimize for mobile networks
// Detect connection speed
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
if (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g') {
// Load minimal resources
loadMinimalVersion();
} else {
// Load full version
loadFullVersion();
}
}
# 6. Mobile-Specific Optimizations
# Viewport configuration
# Preload critical resources
Performance Testing Tools
Performance Testing Setup
Performance Testing Tools
# Performance Testing Tools
# 1. Lighthouse CLI
# Install Lighthouse
npm install -g lighthouse
# Run Lighthouse audit
lighthouse http://localhost:3000 --output html --output-path ./lighthouse-report.html
# Lighthouse CI configuration
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
numberOfRuns: 3
},
assert: {
assertions: {
'categories:performance': ['error', {minScore: 0.9}],
'first-contentful-paint': ['error', {maxNumericValue: 2000}],
'largest-contentful-paint': ['error', {maxNumericValue: 2500}],
'cumulative-layout-shift': ['error', {maxNumericValue: 0.1}]
}
}
}
};
# 2. WebPageTest Integration
# WebPageTest API
const webpagetest = require('webpagetest');
const wpt = new webpagetest('https://www.webpagetest.org');
wpt.runTest('http://example.com', {
runs: 3,
location: 'Dulles:Chrome',
firstViewOnly: false
}, (err, data) => {
if (err) {
console.error(err);
return;
}
console.log('Test ID:', data.testId);
// Check results
wpt.getTestResults(data.testId, (err, results) => {
if (err) {
console.error(err);
return;
}
console.log('First View Load Time:', results.data.average.firstView.loadTime);
console.log('Speed Index:', results.data.average.firstView.SpeedIndex);
});
});
# 3. Performance Budget
# Webpack performance budget
module.exports = {
performance: {
maxAssetSize: 250000,
maxEntrypointSize: 250000,
hints: 'warning'
}
};
# 4. Automated Performance Testing
# Jest performance tests
describe('Performance Tests', () => {
test('page load time should be under 3 seconds', async () => {
const startTime = Date.now();
await page.goto('http://localhost:3000');
await page.waitForLoadState('networkidle');
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(3000);
});
test('LCP should be under 2.5 seconds', async () => {
await page.goto('http://localhost:3000');
const lcp = await page.evaluate(() => {
return new Promise((resolve) => {
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
resolve(lastEntry.startTime);
}).observe({entryTypes: ['largest-contentful-paint']});
});
});
expect(lcp).toBeLessThan(2500);
});
});
# 5. Performance Monitoring Dashboard
# Real-time performance monitoring
const express = require('express');
const app = express();
// Performance metrics endpoint
app.get('/api/performance', (req, res) => {
const metrics = {
timestamp: Date.now(),
url: req.query.url,
metrics: {
fcp: req.query.fcp,
lcp: req.query.lcp,
fid: req.query.fid,
cls: req.query.cls
}
};
// Store metrics in database
storeMetrics(metrics);
res.json({status: 'success'});
});
// Performance dashboard
app.get('/dashboard', (req, res) => {
const metrics = getMetrics();
res.render('dashboard', {metrics});
});
Best Practices
Performance Optimization Checklist
Frontend Optimization
- Optimize images and use WebP
- Minify CSS and JavaScript
- Implement lazy loading
- Use critical CSS
- Enable compression
- Implement caching
- Use CDN for static assets
Backend Optimization
- Enable HTTP/2
- Implement database indexing
- Use connection pooling
- Optimize database queries
- Implement caching layers
- Use compression
- Monitor performance metrics
Summary
Website speed optimization involves several key components:
- Core Web Vitals: LCP, FID, CLS monitoring and optimization
- Image Optimization: Compression, WebP, responsive images
- CSS Optimization: Critical CSS, minification, purging
- JavaScript Optimization: Code splitting, bundling, performance
- Server Optimization: HTTP/2, compression, caching
- Performance Monitoring: Web Vitals, RUM, automated testing
- Mobile Optimization: Responsive design, PWA, touch optimization
- Testing Tools: Lighthouse, WebPageTest, performance budgets
Need More Help?
Struggling with website speed optimization or need help improving your Core Web Vitals? Our performance experts can help you optimize your website for better speed and user experience.
Get Performance Help