E-commerce : optimiser le temps de chargement
Une seconde de chargement en plus = 7% de conversions en moins. Sur un site e-commerce, la performance n'est pas un luxe technique, c'est du chiffre d'affaires. Voici comment optimiser concrètement.
L'impact business de la performance
Les chiffres sont sans appel :
Exemple concret
Un site e-commerce à 100 000€/mois qui passe de 4s à 2s de chargement peut espérer +15-20% de conversions, soit 15-20k€/mois supplémentaires. L'optimisation se rentabilise en quelques semaines.
Mesurer avant d'optimiser
Pas d'optimisation à l'aveugle. Mesurez d'abord.
Outils de mesure
- Google PageSpeed Insights : score et recommandations
- GTmetrix : waterfall détaillé
- WebPageTest : tests multi-localisation
- Chrome DevTools : analyse réseau et performance
- Core Web Vitals : métriques Google (LCP, FID, CLS)
Métriques clés à suivre
LCP (Largest Contentful Paint) : <2.5s - temps avant affichage du contenu principal
FID (First Input Delay) : <100ms - réactivité aux interactions
CLS (Cumulative Layout Shift) : <0.1 - stabilité visuelle
TTFB (Time To First Byte) : <600ms - temps de réponse serveur
Les images : 60% du problème
Sur un site e-commerce, les images produits représentent souvent 60-80% du poids des pages. C'est là qu'il faut commencer.
Format moderne : WebP et AVIF
HTML avec fallback
<!-- Format moderne avec fallback -->
<picture>
<source srcset="product.avif" type="image/avif">
<source srcset="product.webp" type="image/webp">
<img src="product.jpg" alt="Produit">
</picture>
Gains typiques : WebP = -30% vs JPEG. AVIF = -50% vs JPEG. Sur une fiche produit avec 5 images, ça peut représenter 500KB économisés.
Lazy loading natif
Lazy loading
<!-- Ne charge que quand visible -->
<img
src="product.webp"
loading="lazy"
decoding="async"
alt="Produit"
>
<!-- SAUF pour les images above-the-fold -->
<img
src="hero.webp"
loading="eager"
fetchpriority="high"
alt="Hero"
>
Images responsives
Srcset pour différentes tailles
<img
srcset="
product-400.webp 400w,
product-800.webp 800w,
product-1200.webp 1200w
"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
src="product-800.webp"
alt="Produit"
>
Erreur courante : Servir des images 2000px sur mobile. Un smartphone n'a pas besoin de plus de 400-600px de large pour une image produit.
Le cache : ne pas refaire ce qui est déjà fait
Cache navigateur
Configuration Nginx
# Assets statiques : cache long
location ~* \.(css|js|jpg|jpeg|png|webp|avif|gif|ico|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML : cache court avec revalidation
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
CDN (Content Delivery Network)
Pourquoi un CDN est essentiel
Un CDN distribue vos assets sur des serveurs proches de vos utilisateurs. Un visiteur à Marseille ne charge pas les images depuis un serveur parisien.
Options populaires : Cloudflare (gratuit pour commencer), AWS CloudFront, Fastly, BunnyCDN.
Cache applicatif
Cache des requêtes lourdes (Laravel)
// Cache la liste des catégories (change rarement)
$categories = Cache::remember('categories', 3600, function() {
return Category::with('children')->get();
});
// Cache les produits populaires
$popular = Cache::remember('products.popular', 900, function() {
return Product::popular()->take(12)->get();
});
JavaScript : le tueur silencieux
Le JavaScript bloque le rendu et consomme du CPU. Sur mobile, c'est souvent le principal facteur de lenteur.
Charger intelligemment
Chargement optimisé
<!-- Critique : dans le head avec defer -->
<script src="critical.js" defer></script>
<!-- Non-critique : chargé après -->
<script src="analytics.js" async></script>
<!-- Widgets externes : lazy load -->
<script>
// Charge le chat uniquement après interaction
document.addEventListener('scroll', function loadChat() {
const script = document.createElement('script');
script.src = 'https://chat-widget.com/embed.js';
document.body.appendChild(script);
document.removeEventListener('scroll', loadChat);
}, { once: true });
</script>
Les coupables habituels
- Widgets de chat : souvent 200-500KB de JS
- Pixels de tracking : Facebook, Google, etc. s'accumulent
- Sliders/carousels : bibliothèques lourdes pour peu de valeur
- Polyfills inutiles : support de vieux navigateurs non nécessaire
Code splitting
Import dynamique (React/Vue)
// Charge le composant checkout uniquement sur la page panier
const Checkout = lazy(() => import('./Checkout'));
// Charge la galerie uniquement quand nécessaire
const ProductGallery = lazy(() => import('./ProductGallery'));
CSS : render-blocking minimisé
CSS critique inline
Head optimisé
<head>
<!-- CSS critique inline pour le first paint -->
<style>
/* Header, hero, navigation - above the fold */
.header { ... }
.hero { ... }
</style>
<!-- CSS complet chargé en async -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>
Purger le CSS inutilisé
Un thème e-commerce charge souvent 200-500KB de CSS dont 70% n'est jamais utilisé. Des outils comme PurgeCSS ou UnCSS suppriment automatiquement le code mort.
Base de données : les requêtes qui tuent
Sur une page catégorie avec 50 produits, une requête N+1 peut générer 150+ requêtes SQL au lieu de 3.
Eager loading obligatoire
Requêtes optimisées
// MAUVAIS : N+1 queries
$products = Product::all();
foreach ($products as $product) {
$product->category->name; // 1 requête par produit!
$product->images; // encore 1 requête!
}
// BON : 3 requêtes total
$products = Product::with(['category', 'images', 'brand'])->get();
Index sur les colonnes filtrées
Index essentiels e-commerce
-- Recherche par catégorie + tri
CREATE INDEX idx_products_category_price
ON products(category_id, price);
-- Filtres courants
CREATE INDEX idx_products_filters
ON products(category_id, brand_id, in_stock, price);
-- Recherche texte
CREATE FULLTEXT INDEX idx_products_search
ON products(name, description);
Checklist d'optimisation e-commerce
Images
- ☐ Format WebP/AVIF avec fallback
- ☐ Lazy loading sur les images below-the-fold
- ☐ Images responsives (srcset)
- ☐ Compression optimisée (qualité 80-85%)
- ☐ Dimensions correctes (pas de redimensionnement CSS)
Cache & CDN
- ☐ CDN configuré pour les assets
- ☐ Headers cache appropriés
- ☐ Cache applicatif sur les données stables
- ☐ Page cache pour les pages publiques
Code
- ☐ JS defer/async approprié
- ☐ CSS critique inline
- ☐ Minification JS/CSS
- ☐ Code splitting
- ☐ Suppression des scripts inutiles
Backend
- ☐ Eager loading des relations
- ☐ Index sur les colonnes filtrées
- ☐ TTFB < 600ms
- ☐ Compression Gzip/Brotli
Besoin d'aide sur votre projet ?
Je peux vous accompagner dans le développement ou l'optimisation de votre application.
Me contacter