Comment J'ai Réduit le Temps de Chargement de 8s à 0.8s (Case Study)
Étape par étape, les optimisations exactes qui ont transformé un site e-commerce lent en fusée.

title: "Comment J'ai Réduit le Temps de Chargement de 8s à 0.8s (Case Study)" description: "Étape par étape, les optimisations exactes qui ont transformé un site e-commerce lent en fusée." date: "2025-12-13" author: "Équipe Raicode" tags: ["performance", "Core Web Vitals", "optimisation", "case study", "e-commerce"] category: "Performance" image: "/blog/temps-chargement-8s-08s-hero.png" ogImage: "/blog/temps-chargement-8s-08s-hero.png" keywords: ["optimisation performance web", "temps de chargement", "Core Web Vitals", "vitesse site web", "LCP optimisation"]
Le site : Un e-commerce de mode avec 3 500 produits. Le problème : 8.2 secondes de chargement sur mobile. Taux de rebond à 67%. Le résultat : 0.83 secondes. Taux de rebond à 31%. CA +47% en 3 mois.
Voici exactement ce qu'on a fait.
L'Audit Initial : L'Horreur
Les Métriques de Départ
Lighthouse Mobile : 23/100 💀
LCP (Largest Contentful Paint) : 8.2s
FID (First Input Delay) : 340ms
CLS (Cumulative Layout Shift) : 0.42
Time to Interactive : 12.4s
Total Page Weight : 14.2 MB
Les Problèmes Identifiés
- Images non optimisées : Photos produits en 4000x4000px, format JPG
- JavaScript bloquant : 47 scripts tiers (analytics, chat, pixels...)
- Pas de mise en cache : Tout rechargé à chaque visite
- Serveur lent : Hébergement mutualisé cheap
- Fonts personnalisées : 6 variantes chargées en render-blocking
- Carrousel géant : 12 images en autoplay sur la homepage
- Base de données non optimisée : Requêtes en 2-3 secondes
Phase 1 : Les Quick Wins (Jour 1-2)
Optimisation #1 : Images → -4.2s
Avant :
<img src="product-photo.jpg" />
<!-- 4000x4000px, 2.8MB par image -->
Après :
<img
src="product-photo.webp"
srcset="
product-photo-400.webp 400w,
product-photo-800.webp 800w,
product-photo-1200.webp 1200w
"
sizes="(max-width: 768px) 100vw, 50vw"
loading="lazy"
decoding="async"
width="800"
height="800"
/>
Actions :
- Conversion automatique en WebP (85% de compression en plus)
- Génération de variantes responsive
- Lazy loading sur toutes les images below the fold
- Dimensions explicites pour éviter le CLS
Impact : -4.2s de LCP, -8.7MB de poids total
Optimisation #2 : Scripts Tiers → -1.8s
Avant : 47 scripts chargés en synchrone
<script src="analytics.js"></script>
<script src="chat-widget.js"></script>
<script src="facebook-pixel.js"></script>
<script src="hotjar.js"></script>
<!-- ... 43 autres -->
Après :
<!-- Scripts critiques uniquement, différés -->
<script defer src="analytics-minimal.js"></script>
<!-- Le reste chargé après interaction utilisateur -->
<script>
// Chargement lazy des scripts non-critiques
document.addEventListener('scroll', () => {
loadNonCriticalScripts();
}, { once: true });
setTimeout(loadNonCriticalScripts, 5000);
</script>
Actions :
- Suppression de 23 scripts inutiles ou redondants
- Defer/async sur tous les scripts restants
- Chargement conditionnel (chat après scroll, pixels après consentement)
- Bundle des scripts similaires
Impact : -1.8s de Time to Interactive
Optimisation #3 : Fonts → -0.6s
Avant :
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-regular.woff2');
/* 6 variantes, toutes chargées au démarrage */
}
Après :
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-regular.woff2');
font-display: swap;
unicode-range: U+0000-00FF; /* Latin de base uniquement */
}
/* Préchargement de la font critique */
<link rel="preload" href="/fonts/custom-regular.woff2" as="font" crossorigin>
Actions :
- Réduction à 2 variantes (regular + bold)
- Subsetting (caractères latins uniquement)
- font-display: swap pour éviter le blocage
- Préchargement de la font principale
Impact : -0.6s, CLS éliminé sur les textes
Phase 2 : Infrastructure (Jour 3-5)
Optimisation #4 : Changement d'Hébergement → -0.9s
Avant : Hébergement mutualisé OVH à 5€/mois
- TTFB : 1.2s
- Pas de HTTP/2
- Pas de CDN
Après : Vercel (frontend) + Railway (backend)
- TTFB : 0.08s
- HTTP/3 activé
- CDN global automatique
Impact : -0.9s de TTFB, meilleure distribution mondiale
Optimisation #5 : Mise en Cache Aggressive
Configuration CDN :
# Assets statiques : 1 an
Cache-Control: public, max-age=31536000, immutable
# Pages HTML : revalidation
Cache-Control: public, max-age=0, must-revalidate
# Images produits : 1 semaine
Cache-Control: public, max-age=604800
Service Worker pour offline-first :
// Cache des pages déjà visitées
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
Impact : Visiteurs récurrents à 0.3s de chargement
Optimisation #6 : Base de Données → -0.5s
Problèmes identifiés :
- Requêtes N+1 sur les pages catégories
- Pas d'index sur les colonnes filtrées
- Jointures non optimisées
Solutions :
-- Ajout d'index stratégiques
CREATE INDEX idx_products_category_price
ON products(category_id, price);
CREATE INDEX idx_products_active_stock
ON products(is_active, stock_quantity);
// Avant : N+1 queries
const products = await db.products.findAll();
for (const p of products) {
p.category = await db.categories.findById(p.categoryId);
}
// Après : 1 query avec jointure
const products = await db.products.findAll({
include: [{ model: Category }]
});
Impact : -0.5s sur les pages catalogue
Phase 3 : Optimisations Avancées (Jour 6-10)
Optimisation #7 : Code Splitting
Avant : Un seul bundle JavaScript de 2.3MB
// Tout importé au démarrage
import HomePage from './pages/HomePage';
import ProductPage from './pages/ProductPage';
import CartPage from './pages/CartPage';
import CheckoutPage from './pages/CheckoutPage';
// ... 47 autres composants
Après : Chargement à la demande
// Import dynamique
const HomePage = lazy(() => import('./pages/HomePage'));
const ProductPage = lazy(() => import('./pages/ProductPage'));
// Route-based splitting
<Route path="/" element={
<Suspense fallback={<Skeleton />}>
<HomePage />
</Suspense>
} />
Impact : Bundle initial de 287KB (vs 2.3MB)
Optimisation #8 : Préchargement Intelligent
<!-- Préconnexion aux domaines tiers -->
<link rel="preconnect" href="https://cdn.shopify.com">
<link rel="dns-prefetch" href="https://analytics.google.com">
<!-- Préchargement des ressources critiques -->
<link rel="preload" href="/hero-image.webp" as="image">
<link rel="preload" href="/critical.css" as="style">
<!-- Prefetch des pages probables -->
<link rel="prefetch" href="/products">
Prefetch au survol :
// Quand l'utilisateur survole un lien, précharge la page
document.querySelectorAll('a').forEach(link => {
link.addEventListener('mouseenter', () => {
const href = link.getAttribute('href');
if (href.startsWith('/')) {
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.href = href;
document.head.appendChild(prefetchLink);
}
}, { once: true });
});
Impact : Navigation perçue quasi-instantanée
Optimisation #9 : Critical CSS
Avant : 1 fichier CSS de 450KB chargé en bloquant
Après :
<!-- CSS critique inline -->
<style>
/* Styles pour above-the-fold uniquement */
.header { ... }
.hero { ... }
.nav { ... }
</style>
<!-- CSS complet en async -->
<link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'">
Génération automatique avec Critters :
// next.config.js
module.exports = {
experimental: {
optimizeCss: true,
},
};
Impact : First Paint -0.8s
Optimisation #10 : Suppression du Carrousel
Le problème : Le carrousel homepage chargeait 12 images de 2MB chacune au démarrage.
La solution : Remplacement par une seule hero image avec CTA clair.
// Avant
<Carousel images={heroImages} autoPlay interval={3000} />
// Après
<HeroImage
src="/hero-optimized.webp"
alt="Collection Été 2025"
priority
/>
Bonus : Les carrousels ont un taux de clic de 1% en moyenne. Une image unique avec bon CTA convertit mieux.
Impact : -12MB, +23% de clics sur le CTA
Les Résultats Finaux
Métriques Après Optimisation
Lighthouse Mobile : 98/100 ✅ (était 23)
LCP : 0.83s ✅ (était 8.2s)
FID : 12ms ✅ (était 340ms)
CLS : 0.01 ✅ (était 0.42)
Time to Interactive : 1.1s ✅ (était 12.4s)
Total Page Weight : 890KB ✅ (était 14.2MB)
Impact Business
| Métrique | Avant | Après | Évolution | |----------|-------|-------|-----------| | Taux de rebond | 67% | 31% | -54% | | Pages/session | 2.1 | 4.7 | +124% | | Durée session | 1:12 | 3:45 | +212% | | Taux conversion | 1.2% | 2.1% | +75% | | CA mensuel | - | - | +47% |
La Checklist Performance
Quick Wins (Impact immédiat)
- [ ] Images en WebP avec srcset
- [ ] Lazy loading sur images below the fold
- [ ] Scripts en defer/async
- [ ] Fonts avec font-display: swap
- [ ] Suppression scripts inutiles
Infrastructure
- [ ] TTFB < 200ms
- [ ] CDN activé
- [ ] HTTP/2 ou HTTP/3
- [ ] Cache headers configurés
- [ ] Compression Brotli/Gzip
Avancé
- [ ] Code splitting par route
- [ ] Critical CSS inline
- [ ] Service Worker
- [ ] Prefetch intelligent
- [ ] Optimisation BDD
Les Outils Utilisés
| Outil | Usage | |-------|-------| | Lighthouse | Audit initial et suivi | | WebPageTest | Tests multi-localisations | | Chrome DevTools | Debug réseau et performance | | Squoosh | Optimisation images manuelle | | Bundle Analyzer | Analyse du JavaScript | | Sentry | Monitoring performance réelle |
Le Mot de la Fin
La performance n'est pas un luxe. C'est un investissement avec un ROI mesurable.
Chaque seconde de chargement en moins = 7% de conversion en plus (source: Portent).
Le site de ce case study n'avait rien de spécial techniquement. Les mêmes optimisations s'appliquent à 90% des sites web.
La question n'est pas "si" vous devez optimiser, mais "quand".
Votre site rame ? On réalise un audit performance gratuit avec rapport détaillé des optimisations prioritaires. Demander un audit
Prêt à lancer votre projet ?
Transformez vos idées en réalité avec un développeur passionné par la performance et le SEO. Discutons de votre projet dès aujourd'hui.

