« Lente », ça veut dire quoi exactement

Avant de chercher une cause, il faut séparer deux choses qui n’ont rien à voir.

Le temps serveur (TTFB)

Le Time To First Byte mesure le temps que met votre serveur à produire la page avant que le navigateur ne reçoive quoi que ce soit. C’est PHP, MySQL, PrestaShop et vos modules. Sur une boutique saine, une page catégorie doit se générer en quelques centaines de millisecondes ; au-delà d’une seconde et demie, il y a un vrai problème côté serveur.

Le temps de rendu (côté navigateur)

Une fois le HTML reçu, le navigateur télécharge les CSS, les JS, les polices et les images, exécute les scripts, calcule la mise en page. C’est là que se jouent les Core Web Vitals : LCP, CLS, INP. Un TTFB excellent peut cohabiter avec un LCP catastrophique si votre image de bannière fait 2 Mo.

Ce sont deux chantiers distincts, avec des causes distinctes. Un rapport PageSpeed qui affiche un mauvais score ne vous dit pas lequel des deux est en cause — il faut regarder la décomposition. Et dans le back-office, seul le temps serveur compte : un back-office lent est presque toujours un problème de base de données ou de modules.

Le cas particulier du « lent par intermittence »

Une boutique rapide à 3 h du matin et poussive à 11 h ne souffre pas des mêmes maux qu’une boutique uniformément lente. L’intermittence pointe vers la contention : voisins bruyants sur un mutualisé, crons qui se chevauchent, réindexation de la recherche, import fournisseur, ou pic de robots sur les pages à facettes.

Mesurer avant de toucher à quoi que ce soit

Je ne modifie jamais un réglage de performance sans mesure préalable. Sinon, on ne sait pas si le gain vient de l’action ou du hasard — et on garde des réglages inutiles qui compliqueront la prochaine montée de version.

Mesurer le TTFB brut

En ligne de commande, cette mesure ne dépend ni du navigateur ni du réseau de l’utilisateur :

curl -o /dev/null -s -w "connect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n" https://votre-boutique.fr/une-categorie

Répétez l’appel cinq ou six fois. Si la première mesure est lente et les suivantes rapides, un cache est en jeu. Si tout est lent, la page se régénère à chaque fois.

Activer le profiler PrestaShop

C’est l’outil le plus sous-utilisé de PrestaShop, et de loin le plus utile. Dans config/defines.inc.php, passez _PS_DEBUG_PROFILING_ à true. Chaque page affiche alors un bandeau avec le temps de chargement, la consommation mémoire, le nombre de requêtes SQL, les requêtes les plus lentes, les requêtes dupliquées et le temps passé par hook et par module. C’est là qu’un module fautif se démasque en trente secondes.

Deux règles : activez-le sur une préproduction quand c’est possible, et remettez-le à false immédiatement après. Le profiler affiche des informations techniques à tous les visiteurs et ralentit lui-même la boutique.

Regarder ce que dit MySQL

Activez le slow query log côté serveur (slow_query_log, long_query_time à 0,5 s pour commencer) et laissez-le tourner quelques heures aux heures de trafic. Les requêtes qui reviennent en boucle sont bien plus intéressantes que la requête la plus lente vue une fois.

Lire les logs

Dans var/logs/ (1.7, 8 et 9) et dans les logs PHP de l’hébergeur. Une boutique lente qui log des dizaines de warnings par page paie ces warnings en temps d’exécution et en écriture disque.

Le socle : hébergement, PHP, MySQL

L’hébergement mutualisé

PrestaShop n’est pas un blog. C’est une application Symfony avec un ORM, un moteur de templates et une base relationnelle sollicitée en permanence. Sur un mutualisé d’entrée de gamme, vous partagez CPU, I/O disque et serveur MySQL avec des centaines de sites, et vous subissez des limites invisibles : nombre de processus PHP simultanés, temps CPU par requête, connexions MySQL.

Le symptôme typique : la boutique tient très bien à 20 visiteurs et s’effondre à 60, ou devient lente pendant qu’un import tourne. Cela dit, je ne recommande jamais un changement d’hébergement en premier. Migrer une boutique lente vers un serveur plus puissant, c’est payer plus cher pour masquer le problème. Je mesure d’abord ; quand l’hébergement est réellement le facteur limitant, cela se voit dans les chiffres.

La version de PHP

PrestaShop 9 exige PHP 8.1 au minimum, et l’écart de performance entre PHP 7.x et PHP 8.x est réel sur du code orienté objet comme celui de PrestaShop. Mais attention : on ne change pas de version de PHP sans vérifier les modules. Un module ancien qui utilise une fonction supprimée provoque une erreur 500 immédiate. Si votre boutique est en 1.6 ou 1.7, la question de la version de PHP est indissociable de celle de la montée de version — voir passer de PrestaShop 1.7 à 9.

OPcache et la configuration PHP

Sans OPcache, PHP recompile tous les fichiers de PrestaShop à chaque requête. Vérifiez opcache.enable, et surtout opcache.memory_consumption et opcache.max_accelerated_files : PrestaShop compte des milliers de fichiers, et un cache d’opcode trop petit se vide en permanence, ce qui est presque pire que pas de cache du tout. Vérifiez aussi memory_limit et max_execution_time, souvent trop bas pour le back-office.

Les réglages PrestaShop qui coûtent le plus cher

Tout se joue dans Paramètres avancés > Performance. Je commence systématiquement par cet écran, parce que les mauvais réglages y sont fréquents et que les corriger ne coûte rien.

Le mode debug laissé actif

Dans le même écran, ou dans config/defines.inc.php via _PS_MODE_DEV_. En production, il doit être désactivé. Il affiche les erreurs, désactive certaines optimisations et alourdit chaque page. Je le retrouve actif sur une boutique sur cinq, généralement oublié après une intervention.

Le cache Smarty

Trois réglages comptent :

  • Compilation des templates : en production, « Ne jamais recompiler les fichiers de template ». L’option « Forcer la compilation » fait recompiler tout Smarty à chaque affichage — c’est un réglage de développement, jamais de production.
  • Cache : activé.
  • Cache multi-front et console de débogage Smarty : désactivés sauf besoin précis.

CCC : combiner, compresser, mettre en cache

Le CCC regroupe les CSS et les JS en un nombre réduit de fichiers. Sur une boutique qui empile vingt modules, cela supprime des dizaines de requêtes HTTP. Deux réserves de terrain : le CCC révèle parfois des conflits JavaScript latents (un script qui dépendait de l’ordre de chargement), et il rend le débogage front plus pénible. Activez-le, puis testez le parcours d’achat complet, pas seulement la page d’accueil.

Le cache applicatif

PrestaShop sait utiliser un cache objet : système de fichiers, APCu, Memcached, Redis selon la version et ce que propose votre hébergeur. Redis ou Memcached donnent de bien meilleurs résultats que le cache fichiers sur une boutique à gros catalogue, à condition que le service soit réellement disponible sur le serveur.

Le cache pleine page, qui n’existe pas nativement

C’est le point que beaucoup ignorent : PrestaShop n’a pas de cache pleine page natif. Chaque page est régénérée par PHP. Pour un site à fort trafic, c’est le levier le plus puissant, via un module de cache pleine page (LiteSpeed Cache si votre serveur tourne sous LiteSpeed, ou une solution comme JPresta Page Cache) ou un reverse proxy type Varnish. Attention : un cache pleine page mal configuré sert des paniers ou des prix personnalisés au mauvais visiteur. Les règles d’exclusion (panier, commande, compte client, prix par groupe) se vérifient une par une avant la mise en production.

Modules, images et base de données

Les modules qui chargent tout, partout

C’est la cause n°1 de lenteur front que je rencontre. Quelques classiques :

  • Un module reCAPTCHA qui injecte recaptcha/api.js sur toutes les pages alors qu’il n’est utile que sur le formulaire de contact et l’inscription.
  • Un chat en direct qui charge un widget de plusieurs centaines de kilo-octets, avec ses propres appels réseau, sur chaque page.
  • Les traceurs empilés : Google Ads, Meta Pixel, TikTok, Hotjar, plus un gestionnaire de balises qui en charge d’autres. Chacun paraît léger ; l’addition ne l’est pas.
  • Des modules d’affichage greffés sur displayHeader ou displayFooter qui exécutent des requêtes SQL sur toutes les pages pour un bloc affiché sur une seule.

Le profiler vous donne le temps par module et par hook. C’est cette liste qui doit guider le tri, pas l’intuition. Sur un module tiers mal écrit, on a le choix : le remplacer, le conditionner au bon contexte, ou le réécrire proprement — voir mes interventions PrestaShop.

Les images

PrestaShop 8.1 et suivants permettent de choisir le format généré via le paramètre PS_IMAGE_FORMAT (Design > Paramètres des images) : JPEG, PNG, WebP, AVIF selon la version et les bibliothèques disponibles sur le serveur. Générer du WebP réduit fortement le poids des visuels. Deux pièges : il faut régénérer les miniatures après le changement, et vérifier que le serveur dispose bien de la bibliothèque nécessaire, faute de quoi la génération échoue silencieusement.

Vérifiez aussi les dimensions réelles : une vignette de 250 px affichée à partir d’un fichier de 2000 px, c’est de la bande passante et du décodage gaspillés à chaque vue.

Les requêtes SQL non indexées

Une boutique qui grossit franchit un seuil où des requêtes acceptables deviennent coûteuses. Les suspects habituels : un module d’import qui interroge ps_product par référence sans index sur la colonne, un filtre maison sur ps_product_attribute, une recherche personnalisée en LIKE %terme%. Le profiler et le slow query log les remontent ; EXPLAIN confirme l’absence d’index.

Les tables qui gonflent

PrestaShop enregistre par défaut beaucoup de statistiques. ps_connections, ps_connections_page, ps_connections_source, ps_guest, ps_page_viewed, ps_statssearch et ps_log atteignent des millions de lignes sur une boutique ancienne, essentiellement remplies par des robots. Résultat : un back-office qui rame, des sauvegardes interminables, et un serveur MySQL qui travaille pour rien.

Dans Statistiques > Paramètres, vous pouvez cesser d’alimenter ces tables (PS_STATSDATA_PAGESVIEWS, PS_STATSDATA_CUSTOMER_PAGESVIEWS, PS_STATSDATA_PLUGINS). Purgez ensuite l’historique — après sauvegarde, et en conservant ce dont vous avez réellement besoin. Même réflexe pour les paniers abandonnés vieux de plusieurs années et pour les index de la recherche et de la navigation à facettes, à reconstruire plutôt qu’à laisser s’empiler.

Les erreurs à éviter quand on optimise

  • Changer plusieurs choses à la fois. Vous ne saurez pas ce qui a marché, ni ce qui a cassé le tunnel de commande.
  • Optimiser sans mesure de départ. Sans point de référence, « ça a l’air plus rapide » ne vaut rien.
  • Tout miser sur l’hébergement. Un serveur deux fois plus puissant compense rarement un module qui exécute 400 requêtes par page.
  • Activer un cache pleine page sans règles d’exclusion. Le jour où un client voit le panier d’un autre, le problème de performance devient un problème de confiance.
  • Vider le cache comme réflexe. Si vider le cache « répare » la boutique pendant quelques heures, le cache n’est pas le problème : il masque autre chose. C’est un symptôme, pas une solution — j’en parle dans problèmes de cache PrestaShop.
  • Supprimer des lignes en base sans sauvegarde. Une purge de tables de statistiques mal écrite peut emporter des données de commandes liées.
  • Désactiver des modules au hasard en production. Certains modules laissent des overrides derrière eux ; la désactivation ne suffit pas et peut casser l’affichage.
  • Ignorer le back-office. Une équipe qui passe dix secondes à charger chaque fiche produit perd du temps réel tous les jours.

La méthode que je suis

Sur une boutique PrestaShop lente, je déroule toujours le même ordre. Il n’a rien de spectaculaire, mais il évite de casser une boutique qui marchait.

  1. Établir une mesure de référence. TTFB sur cinq pages types (accueil, catégorie, catégorie filtrée, fiche produit, panier), en front et en back-office, à une heure de trafic normal.
  2. Faire parler la boutique. Profiler activé sur une préproduction, logs var/logs/, logs PHP, slow query log MySQL. On obtient une liste de coupables ordonnée par coût réel.
  3. Corriger le gratuit d’abord. Debug mode, réglages Smarty, CCC, statistiques qui remplissent les tables : quelques minutes de travail, souvent le tiers du problème.
  4. Traiter les modules. Conditionner ou remplacer les plus gourmands, supprimer les modules orphelins et les overrides laissés par des modules désinstallés.
  5. Descendre dans la base. Index manquants, purge raisonnée des tables de statistiques, reconstruction des index de recherche et de facettes.
  6. Ajouter du cache seulement après. Cache objet, puis cache pleine page avec ses exclusions testées une par une. Le cache doit accélérer une boutique saine, pas cacher une boutique malade.
  7. Re-mesurer et documenter. Mêmes pages, même méthode, et une note écrite de ce qui a été modifié et pourquoi — pour la prochaine montée de version.

Si la boutique est en panne plutôt que lente, la démarche est différente : voir dépannage e-commerce. Si vous voulez que quelqu’un prenne ce travail de bout en bout, c’est l’objet de l’optimisation de la performance, et du suivi dans la durée décrit en maintenance.

Checklist

  • Mesurer le TTFB sur cinq pages types avant toute modification, en front et en back-office.
  • Vérifier que le mode debug est désactivé en production (_PS_MODE_DEV_ à false).
  • Régler Smarty sur « Ne jamais recompiler les fichiers de template » et activer le cache.
  • Activer le CCC, puis tester le tunnel de commande complet, pas seulement l’accueil.
  • Activer le profiler (_PS_DEBUG_PROFILING_) sur une copie, relever les modules et requêtes les plus coûteux, puis le désactiver.
  • Identifier les modules qui chargent des scripts tiers sur toutes les pages et les conditionner aux pages utiles.
  • Passer les images en WebP via PS_IMAGE_FORMAT et régénérer les miniatures.
  • Couper l’enregistrement des statistiques de navigation, puis purger ps_connections, ps_guest et ps_log après sauvegarde.
  • Activer le slow query log MySQL quelques heures et corriger les index manquants.
  • N’ajouter un cache pleine page qu’en dernier, avec des règles d’exclusion testées sur panier, commande et compte client.

Questions fréquentes

Faut-il changer d’hébergeur pour accélérer PrestaShop ?

Rarement en premier. Dans la majorité des boutiques que j’examine, la lenteur vient de modules, de requêtes SQL, de tables encombrées ou de réglages de cache inadaptés — autant de choses qu’un serveur plus puissant ne fait que masquer. Je mesure d’abord. Quand l’hébergement est réellement le facteur limitant, cela se voit dans les chiffres, et le changement se justifie alors sans discussion.

PrestaShop a-t-il un cache pleine page natif ?

Non. PrestaShop dispose d’un cache de templates (Smarty), d’un cache objet et du CCC pour les assets, mais chaque page est régénérée par PHP à chaque visite. Pour un cache pleine page, il faut passer par un module dédié (LiteSpeed Cache si votre serveur tourne sous LiteSpeed, ou une solution commerciale de page cache) ou par un reverse proxy. C’est un levier puissant, mais qui exige des règles d’exclusion rigoureuses.

Mon back-office est lent alors que le front va bien. Pourquoi ?

Le back-office ne bénéficie ni du cache de pages ni du CCC front, et il interroge massivement la base. Les causes habituelles sont les tables de statistiques devenues énormes, un catalogue avec beaucoup de déclinaisons, des modules greffés sur les hooks d’administration, et une memory_limit PHP trop basse. Le profiler fonctionne aussi en back-office : c’est par là que je commence.

Vider le cache rend ma boutique rapide pendant quelques heures, puis ça recommence. Que faire ?

C’est le signe que le cache se régénère mal ou qu’il est invalidé en permanence — souvent par une tâche cron, un import fournisseur ou un module qui écrit en configuration à chaque page. Vider le cache traite le symptôme. Il faut trouver ce qui l’invalide, en regardant les crons, les logs et les écritures en base aux heures où la dégradation apparaît.

Le CCC peut-il casser ma boutique ?

Il peut révéler des conflits JavaScript qui existaient déjà mais que l’ordre de chargement masquait. Les symptômes typiques : un carrousel qui ne démarre plus, un bouton d’ajout au panier inerte, un sélecteur de déclinaisons figé. Activez-le sur une préproduction, testez tout le parcours d’achat, et si un module pose problème, corrigez ce module plutôt que de renoncer au CCC.