Optimisation WordPress

L’énergie la moins chère c’est celle qu’on ne dépense pas
HTTP + WordPress + PHP + MySQL = cher
Cache = pas cher

Pourquoi optimiser ? et pourquoi optimiser WordPress ?
Comment mesurer l’optimisation d’un site, avec Pingdom, Firebug, Yahoo Slow et Google Page Speed

Optimisation des performances de WordPress :
Sur Apache, en ajoutant des headers Expire, en compressant le contenu, en ajoutant des Etags, en utilisant des sous domaines, en installant un opcode cache
Du coté MySQL, en activant le cache et en loggant les requêtes longues.
Sur WordPress, en faisant attention aux plugins, en activant le cache avec WP Super Cache, en rassemblant les fichiers JS et CSS avec PHP Speedy, en désactivant la sauvegarde automatique

L’optimisation, pour quoi ?

Economiser de la ressource
Sur le même serveur/hébergement mutualisé qui peut servir 1000 visiteurs par jour avec un WordPress par défaut, vous pourrez servir 10 000 visiteurs avec un WordPress optimisé.
(chiffres arbitraires, mais l’ordre de grandeur est constaté en situation réelle).

Un mutualisé coute 10 EUR par mois, un dédié 100 EUR.
Un dédié d’entrée de gamme 50 EUR, un haut de gamme 200 EUR.
Sur un même dédié, vous pouvez héberger trois WordPress par défaut (moyen trafic) ou trente WordPress optimisés (moyen trafic)

Servir tous vos visiteurs
Quand les ressources ne suivent plus, vos visiteurs ne voient plus votre site, mais recoivent une page d’erreur (500, 404, ou autres selon les hébergeurs).
On a beau se consoler en se disant que le site progresse, que les ralentissements sont un petit à coté, on se dit quand meme que +30% de trafic par mois, c’est mieux que +10 %.

Et puisque le back office et le front office sont généralement sur le même hébergement, songez qu’en périodes de fêtes/commandes, sur un site de ecommerce, le back office (gestion des commandes) ralentit au moment même ou le gestionnaire de la boutique l’utilise le plus…

Anticiper les montées de trafic et les coups de buzz
Vous servez 1 500 visiteurs par jour, votre pack mutualisé tient le coup.
Vous servez 10 000 visiteurs par jour sur un dédié, le load average tient de 0.8 à 2.
Vous vous pensez à l’abri.

Un gros lien, un forum US, un email qui circule, un coup de digg-like, et vous avez 20 000 visiteurs dans les deux heures. Le serveur explose, la moitié des visiteurs ne verra pas votre site.

Vous venez de perdre 200 abonnés à votre flux RSS.
Les sites de vos clients hébergés sur le même serveur viennent de prendre 4 heures d’indisponibilité. Pire encore, c’est le site du client qui a pris un coup de buzz, et c’est 80 commandes que vous venez de lui faire perdre.
Vous avez une bonne assurance ?

Chiffres déjà constatés en situation réelle :

  • Les mails des visiteurs (“envoyez cette page à un ami”) qui apportent 5 à 10 000 visiteurs dans la journée.
  • Un site qui prend +100% par semaine pendant 3 mois, et passe de 1 000 visiteurs jours à 100 000 visiteurs
  • Un lien qui apporte 20 000 visiteurs dans l’heure
  • Un buzz qui apporte 50 000 visiteurs dans la journée
  • Un seul lien qui amène 9 millions de visiteurs en 2 heures

Optimiser votre référencement.
Le temps de chargement des pages est un facteur de positionnement.

“What impact does site load times have on Google rankings ? ”
(Quel est l’impact du temps de chargement sur les positionnements ?
L’intervention de Matt Cutts sur le sujet.

Réponse de Matt Cutts : Si une page est trop lente (20-30 secondes) pour que Googlebot la récupère, elle ne pourra pas être indexée.
Mais 1 seconde ou 2 secondes c’est pareil.
Larry Page veut que le web soit rapide. Très rapide. Aussi rapide qu’un livre : quand vous tournez la page, vous voyez tout de suite la page suivante.
Ce qui pourrait arriver dans le futur, je ne sais pas, mais j’imagine assez bien que Google se dit “nous aimerions bien que le web soit plus rapide ; que pouvons nous faire pour encourager les gens à faire des sites web plus rapides ? On pourrait établir le fait que plus un site est rapide, les visiteurs seront plus contents, et plus enclins à revenir

À votre avis, entre :

  • un site professionnel, avec une équipe technique et des moyens adaptés, dont les pages se chargent en 0.8 seconde de moyenne (faisons semblant de croire un instant que les agences web savent optimiser Apache. Ah. Ah Ah)
  • et un site amateur branché sur un pack mutu, dont les pages se chargent en 3 à 4 secondes (mesure classique sur un blog chargé en pack mutu)

Lequel de ces deux sites sera regardé avec le plus de confiance par GoogleBot ?
Lequel de ces deux sites sera crawlé le plus souvent ? (on sait que GoogleBot adapte sa cadence de crawl à la vitesse du serveur, pour ne pas exploser les petits sites)
Lequel de ces deux sites sera crawlé le plus profondément ?

J’ai un pack mutualisé, pourquoi me préoccuper de la charge serveur ?
En dehors de la simple bonté d’âme pour votre hébergeur, vous avez un intérêt direct à optimiser votre installation WordPress.

  • Vos visiteurs ne seront pas refoulés à l’entrée
  • Vos visiteurs consulteront votre site plus rapidement.
  • Vous pourrez rester plus longtemps sur le même pack mutualisé sans être forcé de monter en gamme.
  • Le back office (administration) sera plus fluide

L’optimisation WordPress, pourquoi ?

WordPress par défaut, deuxième visite WordPress optimisé, deuxième visite
1 page WordPress

1 requête HTTP pour la page
5-30 requêtes HTTP pour les fichiers
1 vérification de cookie
1 processus PHP
30 à 150 requêtes MySQL (voir plus avec certains plugins)

5 à 50 requêtes HTTP
Exemple : 1 page, 6 CSS, 9 JS, 12 images = 28 requêtes, soit 224 Mo de mémoire
Quelques dizaines ou centaines de ko de transfert

2Go de RAM = vous pouvez servir 10 visiteurs simultanément.

1 requête HTTP pour la page, servie en statique, et en compressé
1 vérification de cookie
0 transfert pour les fichiers multimédia (éventuellement quelques en-têtes)

1 requête HTTP, quelques ko de transfert
2Go de RAM = vous pouvez servir 256 visiteurs simultanément

1 fichier (CSS,JS,image) de 80ko

1 requête HTTP
1 vérification de cookie
80 ko de transfert (taille du fichier + en têtes)

0 ko

Eventuellement une requête HTTP avec quelques octets d’en-têtes pour vérifier la validité du cache.
Si fichier sur le même domaine : une vérification de cookie

Résultat

Multipliez ca par 1000 clients pendant une heure (10-15 000 visiteurs uniques jour), sur un blog buzz ou un site un peu chargé en multimédia, vous mettez par terre un dédié moyen de gamme.

VIENS CHERCHER BONHEUR
Vous servez vos pages plus vites,
vos visiteurs sont satisfaits,
vous économisez des ressources.

Comment mesurer la rapidité d’un site

Pingdom

Avec l’outil Pingdom, vous pouvez constater visuellement la rapidité d’un site.
pingdom

Firebug

FireBug vous permet de tester la rapidité de chargement de votre site.
L’avantage de Firebug est qu’il affiche en direct les headers renvoyés (200/304, etc.). Sur les fichiers JS/CSS/Image, on cherchera à avoir autant de 304 que possible.
firebug

Yahoo Slow

Yahoo Slow est l’outil développé par Yahoo pour mesurer la performance d’un site Web.
Yahoo Slow permet d’auditer rapidement un site Web et d’avoir des conseils d’optimisation.
Par exemple sur cette image, Yahoo Slow donne une note de 43/100 au site lemonde.fr, et recommande de :
– compresser 31 javascripts en 1 seul fichier
– compresser 12 feuilles de style en 1 seule feuille
– diminuer le nombre d’images (69)
– utiliser un sous domaine ou un CDN pour servir les contenus multimédias
– ajouter des headers Expires sur 161 fichiers
– rajouter des ETags

yslow1

Dans l’onglet “Statistics”, vous pouvez voir l’analyse d’un “premier chargement” et d’un “deuxième chargement”. L’idéal est de réduire le nombre de requêtes du deuxième chargement (on peut descendre à 1-5 requetes, aussi légères que possibles), et de minimiser le nombre de requêtes du premier chargement (dont le nombre dépend de l’optimisation de votre thème et du nombre de vos fichiers)
yslow2
Pour référence, un WordPress nu sur un serveur non configuré tourne dans les 40-70 / 100 au Yahoo Slow. Il est raisonnable de viser entre 90 et 100/100 après optimisation.

Google Page Speed

Le dernier né des outils d’optimisation, Google Page Speed pratique à peu pres les mêmes tests que Yahoo Slow.
L’outil est un peu plus jeune, mais il offre en particulier des raccourcis vers les versions compressés de JS et CSS.
pagespeed


L’optimisation, comment ?

Apache : Ajoutez des headers Expire (valable pour tous les sites)

Le mod_expires d’Apache permet de gérer les dates d’expiration des fichiers.
Avec mod_expires configuré, quand le serveur envoie une image au client, il lui précise que cette image est “valable” pour les 15 prochains jours (par exemple). Le client ne demandera donc plus l’image pendant 15 jours.
Si le client lit 100 pages sur les 15 prochains jours, une image de 10ko coûtera 1Mo de bande passante sans expires, 10 ko avec expires.

En pratique, on n’indique pas 15 jours mais plus souvent 2 ans, ce qu’on appelle les “Far Future Expire Headers” (“en-têtes d’expiration dans un futur lointain”)

Si vous avez des fichiers qui sont susceptibles de changer plus souvent, vous pouvez leur adjoindre un numéro de version. Par exemple, votre feuille de style sera liée avec /wp-content/themes/montheme/style.css?ver=20090601
A la prochaine modification, vous lierez avec /wp-content/themes/montheme/style.css?ver=20090615 ce qui forcera le cache à se régénérer.

Indications :
Serveur à fort trafic et contenu multimedia
Mémoire encombrée

Mode d’action :
Diminution brutale du load average : au lieu de 40 ou 50 requêtes par page, le serveur n’en gère plus que 2 ou 3, et quelques négociations d’en-têtes.
Fluidité des chargements de page pour le visiteur

Posologie : configurez mod_expires dans le .htaccess


#CACHE
 ExpiresActive on
#images
 ExpiresByType image/jpg "access plus 2 years"
 ExpiresByType image/jpeg "access plus 2 years"
 ExpiresByType image/gif "access plus 2 years"
 ExpiresByType image/png "access plus 2 years"
 ExpiresByType image/x-icon "modification plus 2 years"
#flash
 ExpiresByType application/x-shockwave-flash "modification plus 2 years"
#css et scripts
 ExpiresByType text/css "modification plus 2 years"
 Header set Cache-Control "max-age=86400, public"
 ExpiresByType text/javascript "modification plus 2 years"
#html/php
 ExpiresByType text/html "modification plus 2 years"
 ExpiresByType text/xml "modification plus 2 years"
#tout le reste
 ExpiresDefault "modification plus 2 years"
 Header set Cache-Control "max-age=86400, public"
### / CACHE


Apache : Compressez les fichiers avec gzip (valable pour tous les sites)

La compression HTTP avec gzip permet de réduire de 5 à 70% la taille des fichiers envoyés du serveur au client. Le processus est complètement transparent pour l’utilisateur, tous les navigateurs sachant décompresser le gzip à la réception.

Indications :
Sites à contenu fortement consultés pendant les heures de pointe

Mode d’action :
Diminue la bande passante consommée
Fluidifie la visite

Effets indésirables :
Avec certains plugins comme PHPSpeedy, désactivez la compression des pages par le plugin, sinon le contenu risque d’être compressé deux fois !

Posologie :
Configurez la compression dans le fichier .htaccess :


AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript application/xhtml+xml application/xml application/rss+xml application/atom_xml

Attention, pour les packs mutualisés 1and1, vous aurez à créer (ou modifier) le fichier php.ini à la racine de votre répertoire, et y ajouter les lignes :

zlib.output_compression = On
zlib.output_compression_level = 5

Apache : Ajoutez des ETags (facultatif) (valable pour tous les sites)

Les Etags sont des identifiants – normalement – uniques à un fichier, qui permet au client de préciser au serveur quelle est la version du fichier qu’il possède en cache.
Leur utilité est discutable, car le serveur sait gérer le cache sans ETag ; mais, en l’absence de contre-indication médicale, ca ne coute pas cher.

Posologie :
Dans le .htaccess :

FileETag MTime Size

Apache : Utilisez un sous domaine

Rappel : www.monsite.com est un sous domaine de monsite.com

Le sous domaine principal (www) doit envoyer au visiteur votre page principale, et quelques fichiers obligatoires. Mais un sous domaine, c’est comme un fournisseur avec 4 camions : il peut vous envoyer 4 chargements en même temps, puis il faut attendre la tournée suivante. Si vous avez pas mal d’images sur vos pages, cette limite de 4 (threads) devient vite limitante.

Vous avez alors intérêt à stocker les images sur un sous domaine (par exemple medias.monsite.com), ce qui permettra de passer à 8 threads simultanés.
C’est aussi la logique qui conduit à utiliser un CDN (Content Delivery NetWork, Réseau de Distribution de Contenu), qui va s’occuper de servir vos fichiers statiques (images, vidéos, css, js), le serveur principal ne servant plus que le contenu dynamique.

Idée pratique :
Configurez un sous domaine qui pointe sur le même répertoire que votre www. ( medias.monsite.com = www.monsite.com ). Ainsi vous pourrez servir du contenu indifférement sur medias ou www.

Attention à ne pas servir le même contenu sur les deux adresses (pour éviter le duplicate)
N’oubliez pas, si besoin est, de configurer le cache Apache sur le sous domaine aussi.


Utilisez un OpCode PHP (valable pour tous les dédiés)

Les opcode permettent de mettre en cache les fichiers PHP (avant interprétation), ce qui évite par exemple au serveur d’avoir à charger tous les fichiers WordPress à chaque chargement de page (les fichiers seront déjà dans le cache).
Je vous renvoie à la littérature pour installer XCache ou eAccelerator.


MySQL : activez le cache des requêtes (facultatif) (valable pour tous les dédiés)

Pour activer le cache query de MySQL, je vous renvoie à la littérature.
Un exemple de configuration de cache dans le my.cnf :

# * Query Cache Configuration
query_cache_limit       = 32M
query_cache_size        = 256M
query_cache_type        = 1
query_cache_min_res_unit = 1024
table_cache             = 2048
thread_cache_size       = 150
tmp_table_size          = 16M
max_heap_table_size     = 16M
join_buffer_size        = 16M
read_buffer_size        = 16M

J’ai rajouté (facultatif), car si vous optimisez tout le reste (Apache, WordPress), le cache des requêtes n’apporte qu’une optimisation marginale, puisqu’il y a beaucoup moins de requêtes répétitives. Et c’est un réglage qui n’est pas toujours accessible (ne concerne que les dédiés).


MySQL : surveillez les requêtes lentes (facultatif) (valable pour tous les dédiés)

Vous prendrez soin, en phase de recherche d’optimisation, ou pour identifier un goulot, de logger les requêtes lentes.
Si vous utilisez un WordPress peu customisé, cette étape est facultative car WordPress est assez bien codé niveau requêtes (vous aurez des requêtes un peu longues, mais pas plus que nécessaire).
Dans le my.cnf

# * Logging and Replication
log-slow-queries        = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_long_format
log-queries-not-using-indexes

WordPress : attention aux plugins

Les plugins WordPress, c’est la cour des miracles. Certains sont codés avec les pieds, rajoutent des tables n’importe ou, les remplissent, explosent vos quotas de taille de bases, générent de lourdes opérations à chaque page (généralement sans aucune utilité), etc.

Exemple typique : les plugins de stats.
En version courte : N’EN UTILISEZ PAS.
Version développée : N’en utilisez PAS qui stockent leurs données en local.

Explication:
Classiquement (bsuite, wpstats), chaque chargement de page insère en PHP une ligne MySQL. Une routine PHP, une requête (voire deux ou trois), et une ligne de plus.
1000 visiteurs par jour pendant 12 mois, 360 000 lignes, avec l’ip, l’user agent, un champ date, bref 40 mo de données qui vont exploser votre petit quota de 100 mo par table (voire 50 chez OVH…).
Le module “User Tracking” de OsCommerce a aussi la même tendance à l’obésité… très pratique quand les commandes ne peuvent plus s’enregistrer parce que le tracking considère de sa mission personnelle de mémoriser les ips des 10 000 derniers visiteurs… (oui, oui… situation vécue)

Solutions : utilisez un système tiers (comme Google Analytics). Eventuellement (mon choix personnel), doublez-le par le plugin WordPress.com Stats, qui stocke les données sur les serveurs WordPress et vous les rend à la demande.

Dans le même ordre d’idées, n’utilisez pas de plugins type “Most Viewed” (Billets les plus lus), qui stockent aussi les visites de pages.

Mise en garde particulière sur le plugin Twitter Tools
Croisé déjà plusieurs fois sur des blogs mal optimisés, le plugin Twitter Tools est particulièrement mal codé. Il rajoute deux requêtes très lourdes à chaque page (un PHP et un CSS), qui peuvent manger 1 seconde de temps de chargement et ralentir considérablement votre blog.


WordPress : utilisez WP Super Cache

WP Super Cache

A mon avis, ce plugin devrait être livré en standard avec toute installation WordPress. Même sur un petit blog, il apporte plus de stabilité, moins de consommation, plus de vitesse.
Un WordPress sans Super Cache, c’est comme une voiture à une seule vitesse. Vous êtes vous deja dit : “Je roule doucement, pas besoin de seconde vitesse” ?

Que fait WordPress Super Cache ?
Il enregistre la page générée par WordPress (dynamique avec PHP et Mysql) en HTML (statique).
Au chargement suivant de la page, il servira directement la page statique, sans utiliser PHP ni MySQL. Le serveur économise donc beaucoup de charge (et quand je dis BEAUCOUP, c’est ici dans un facteur de 10x moins de charge), et gagne considérablement en vitesse : sur un serveur moyen de gamme, une page prendra rarement moins de 0.8 seconde à être générée ; une page statique peut être servie en 0.1 seconde.
(0.8 seconde ca peut sembler peu, mais c’est ici uniquement la page elle-même, il reste encore à charger le JS, le CSS, les fichiers médias… et 0.7 seconde économisée ici, ce sont toutes les requêtes suivantes qui commencent plus tôt)

Le cache HTML est complémentaire au cache Apache, car il permet d’influer sur la rapidité de chargement de la “première” visite. Le cache Apache sert au rechargement de la page (ou au deuxième chargement d’un fichier identique).

Installez Super Cache et passez le aussitot que possible en mode “On” (pas Half On). La configuration est particulièrement simple sur ce plugin déjà bien rodé par des milliers d’installations.

Effets généralement constatés :
Chute brutale de la charge serveur
Augmentation des visiteurs
Expérience utilisateur améliorée


WordPress : utilisez PHP Speedy (valable pour tous les sites)

WP PHP Speedy

La principale utilité de PHP Speedy, c’est de transformer vos fichiers javascript et CSS en version réduite :
Au lieu de : 8 fichiers JS + 4 fichiers CSS, soit 12 requêtes et 350 ko de transfert,
vous aurez avec PHP Speedy : 1 fichier JS + 1 fichier CSS, soit 2 requêtes et 180 ko de transfert.

PHP Speedy unifie les fichiers et les réduit (suppression des espaces et sauts de ligne), pour les servir plus vite.

Attention : N’activez pas les options gzip si vous avez déjà configuré la compression au niveau Apache (Apache 2)


Désactivez la sauvegarde automatique

Depuis la version 2.6, WordPress sauvegarde automatiquement tous vos brouillons. Sur des blogs un peu chargés en contenu, les revisions peuvent prendre une place considérable en base.

Note: en revanche, les revisions ne diminuent pas les performances de votre blog. C’est juste une question de taille de base.

Pour les désactiver, ajoutez cette ligne dans votre wp-config.php :

define('WP_POST_REVISIONS', false);

Si vous souhaitez les supprimer, vous aurez besoin de ca :
Attention à faire une sauvegarde de votre base avant d’exécuter ces requêtes

global $wpdb;
$wpdb->query("DELETE FROM $wpdb->postmeta JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->postmeta.post_id WHERE $wpdb->posts.post_type = 'revision'");
$wpdb->query("DELETE FROM $wpdb->term_relationships JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->term_relationships.object_id = $wpdb->posts.post_id WHERE $wpdb->posts.post_type = 'revision'");
$wpdb->query("DELETE FROM $wpdb->posts WHERE $wpdb->posts.post_type = 'revision'");

Vous gérez un annuaire ? Passez le sur WordPress, avec le plugin zeList

Contact : Je vous ai perdu quelque part, vous voulez en savoir plus, votre service web ou le site de votre entreprise a besoin de moi ?
Vous pouvez me contacter ici (téléphone, mail, etc.)

Rejoindre la conversation

24 commentaires

  1. Que du bon… Énormément de trucs auxquels on ne pense pas, en tout cas pas moi. Pas mal de choses que je connaissais même pas…

    Merci pour ce billet Malaiac.

    El Cherubin / Morgan

  2. Bonjour,
    ton article est vraiement pratique pour tous ceux qui n’y connaissent pas grand chose dans le milieu, donc merci !

    Par contre, pour “configurez mod_expires dans le .htaccess” est-ce qu’on peut tout copier-coller directement dans le fichier ou il faut régler quelque chose ?

  3. Ok, merci !

    Par contre pour ta ligne de code pour “Compressez les fichiers avec gzip” ne marche pas chez moi, ça me met une erreur et j’ai plus de site ! Du coup, j’ai enlevé et c’est bon. J’en ai profité pour installer le plugin WP PHP Speedy mais dans les options, est-ce que tu mets “Oui” dans “gzip page” ?

    Merci…

  4. D’abord, merci pour l’article, ces ressources ne sont que trop rares.
    Ensuite parce que j’ai les mains dedans, un petit :

    define(’WP_POST_REVISIONS’,false);

    dans wp-config.php peut aussi faire économiser de la place en bdd et du cpu pour ceux qui n’ont pas besoin de versionner les différentes versions de leurs articles.

  5. Bien vu, j’ai rajouté des lignes conditionnelles ( ) autour des blocs .htaccess.
    Si la compression gzip est activée avec mod_deflate > pas de gzip dans PHP Speedy
    Si non > gzip

  6. Bonjour,

    Voilà j’ai petit blog chez free que j’essaye avec mes maigres compétences d’optimiser. J’ai essayé d’installer le plugin wp_super cache sans succès. Dans mes lectures à droite et à gauche, j’ai vu qu’il était nécessaire de mettre le dossier cache du répertoire wp-content en 777 or visiblement avec Free ce n’est pas possible (il reste en 755).

    Je me demandais s’il y avait une éventuelle alternative pour les gens comme moi qui sont chez free.

    Merci d’avance pour votre aide.

  7. Très bon tour d’horizon !

    Je rajouterai le très bon APC Cache qui permet de mettre en cache les pages php, ainsi que (comme billy) les sprites qui permettent de gagner sur les entêtes ainsi que le nombre de trames à cause de nombreux threads ouverts.

    Bravo pour ton billet

  8. Bonjour,
    Article précieusement rangé dans mes tablettes, merci pour ce boulot.

    Je suis en train de développer mon premier “vrai” site web, celui de ma boîte, basé sur WP. Et comme tout bon newbie qui se respecte, j’essaie de rester, autant que possible, dans les clous qui balisent les bonnes pratiques.

    Or, il me semble bien qu’Apache ne recommande plus d’utiliser les .htaccess, mais d’utiliser les fichiers de configuration du dossier /etc/apache2/sites-availables. Que quelqu’un m’arrête si je me trompe !!

    Mon problème est donc que j’ai beau faire des copier/coller dans tous les sens possibles pour configurer mon fichier “default” en ajoutant les directives de WP Super Cache, rien à faire, il gueule toujours autant parce qu’il trouve pas les infos qu’il cherche dans le .htaccess.

    Comment résoudre ce problème ?

  9. Excellent article, merci.
    concernant le mode expire-active. Qu’en est il des pages d’accueil et de catégories qui change à chaque nouvel article? Est-ce géré par le code fourni?

Laisser un commentaire