WordPress : corriger l’erreur empty_email error

Lorsque vous enregistrez ou modifiez un utilisateur WordPress, vous ne connaissez pas nécessairement son adresse mail. Dans ce cas WP vous gratifie d’un message d’erreur :

ERREUR : veuillez saisir une adresse de messagerie.
et en anglais :
ERROR: Please enter an e-mail address.

Jusqu’à WP 3.9, la parade était connue. Il suffisait d’ajouter aux fonction de votre thème :

add_action( 'user_profile_update_errors', 'remove_empty_email_error' );
function remove_empty_email_error( $arg ) {
if ( !empty( $arg->errors['empty_email'] ) ) unset( $arg->errors['empty_email'] );
}

Depuis WP 4.0, la classe WP_error est devenue privée, et ça ne fonctionne plus.

Voici la nouvelle syntaxe (depuis 4.1) :

add_action( 'user_profile_update_errors', 'remove_empty_email_error' );
function remove_empty_email_error( $arg ) {
$arg->remove('empty_email');
}

Enjoy !

Share

Accélérer WordPress #8 – Lazy load pour les images

lazy

Alors là, je crois avoir découvert un truc formidable.

Au lieu de charger toutes les photos de la page, le « lazy load » les charge au fur et à mesure que l’on descend (scroll) dans la page. C’est donc une amélioration significative :

  • Moins de requêtes, de kB et de temps pour que le chargement soit déclaré complet
  • Et possiblement un meilleur ranking chez notre Ami

J’ai utilisé le plugin « jQuery lazy load plugin » dont une documentation sommaire et une démo sont disponible ici.

Ca marche « out of the box » pour les images simples :

  • Créer une image vide de 1px x 1px : grey.gif
  • Dans l’éditeur de Post utiliser la syntaxe indiquée
<img class="lazy" src="img/grey.gif" data-original="img/example.jpg" width="640" height="480">

J’ai eu plus de mal à le faire fonctionner pour les images associées à un lien, dont la syntaxe est

<a href="lien_quelconque"><img src"url_image" /></a>

N’hésitez pas à me contacter pour connaître le détail du code.

J’en profite pour vous faire part des nouvelles performances du site www.coach-abondance.com :

Performance www.coach-abondance.com

En résumé

  • Le site commence à apparaître après 0,74 secondes : l’internaute n’a plus le temps de bâiller … [au début, c’était plus de 10 secondes],
  • Le temps total de chargement est de 3,3 secondes [au début, c’était plus de 14 secondes],/li>
  • 13 requêtes sont nécessaires [au lieu de 53] et 483 kB sont chargés [au lieu de 960],
  • Seules les 5 premières images (dont le background) sont chargées « en première instance » [sur la quinzaine présentes sur la page], les autres sont … lazy 🙂 et arrivent quand on scrolle la page

 

Share

Accélérer WordPress #7 – Serveur externe pour gros fichiers

Je n’arrive toujours pas à activer un CDN …

GIF animé coach-abondanceMais je me dis qu’un serveur externe rapide serait bien utile pour afficher les très gros fichiers graphiques, en particulier dans le header (background = 100 ko) et dans la page d’accueil (GIF animé = 400 ko, voir ci-contre), qui représentent plus de la moitié des infos de la page.

J’ai choisi Amazon S3 comme serveur de fichier. Ça marche plutôt bien et facilement, il semble que la première année soit gratuite… A voir !

NB : dans les paramètres « Metadata » des fichiers déposés dans le « bucket », il faut ajouter le champ « cache-control » avec la valeur « max-age=2952000 » (soit 1 mois).

De fait, selon GTMetrix, le temps de chargement de la page est réduit de moitié :-). Webpagetest (en DSL 1.5) est moins élogieux, l’avenir dira si le score « hors rebond » de Google Analytics s’améliore … ou pas !

Share

Accélérer WordPress #6 – CSS sprites

CSS spritesSelon les « canons » de l’accélération d’un blog, la réduction du nombre de requêtes est un « must ». A l’examen de mon site, il y a 5 appels de fichiers image dans le header.php. Si le total d’octets récupéré n’est pas énorme, à chaque fois il faut établir une connexion, soit 50-100 ms environ. Ce sont autant de requêtes qui retardent le chargement des autres éléments (puisque 5 requêtes sont exécutées simultanément).

Je lis quelque part que les « CSS sprites » sont une solution efficace. Tous les visuels sont inclus dans un seul fichier (voir image) qui n’est chargé qu’une seule fois (une fois pour toutes), et les images sont « extraites » de ce « master » selon le besoin. Par exemple ici, pour les 6 visuels je ne charge le fichier qu’une seule fois, et je réduis donc de 5 le nombre de requêtes.

Par la même occasion, les appels des images sont effectuées directement depuis le css, ce qui réduit d’autant le temps de téléchargement de la page (les css étant appelées après la page HTML).

[Edit] J’ai intégré ces images dans le fichier « background » hébergé sur Amazon S3. Elles sont cachées par le « container » et ça fait un requête en moins …

Share

Accélérer WordPress #5 – Supprimer des plugins

Une bonne partie du temps de chargement de votre blog est occupée à l’activation des plugins. Vous avez ajouté des fonctionnalités essentielles, vous avez plus de 20 plugins actifs ? Oui, moi aussi, et je sais : c’est trop !

C’est d’autant plus « trop » que WordPress n’optimise pas vraiment l’ordre (ni le moment) de chargements des plugins. En fait, je crois bien qu’ils sont tous là, sur chacune des pages, qu’ils soient utilisés ou non.

Je vais partager ici mes trouvailles.

Supprimer « Related Posts »

Il existe plusieurs plugins qui affichent, pour chaque article, les « articles suggérés ». C’est bien pratique dans un blog où les articles disparaissent sous la pile, même s’ils traitent de sujets très proches.Je recommande vraiment de suggérer d’autres articles à lire.

J’avais installé « WordPress related posts » qui fait vraiment bien son travail : il faut juste 0,2 secondes pour charger les CSS sur la page d’accueil, qui est statique et n’a pas de « related post » !

La suggestion des articles s’effectue de manière usuelle sur la base des mots clés : il est donc très important :

  • D’en mettre (alors que ça ne sert pas du tout au référencement)
  • Et de vérifier régulièrement s’il n’y a pas trop de doublons mal orthographiés (oui, ça m’arrive aussi …)

Je vous recommande cet excellent article (en anglais) qui décrit le bout de code à ajouter à votre template « single.php », juste avant <?php comments_template(); ?>, pour afficher les vignettes (thumbnails) et les titres des articles suggérés en bas de chacun de vos posts.

Bien entendu, vous adapterez le code si, au lieu des vignettes, vous préférez une liste à puce (c’est mon cas, j’ai le titre + les 150 premiers caractères de l’article).

Supprimer « Share Post »

Je pense que c’est aussi une fonctionnalité essentielle (surtout pour les plus jeunes) : un click et c’est sur Facebook, LiknedIn, Twitter … J’avais « share and follow » (non, je ne mets pas de lien) qui est une usine à gaz : près de 0,8 secondes, rien que pour charger l’image à partir de laquelle les vignettes sont extraites …

Ça me manque un peu, alors si vous avez une soluce je suis preneur …

[Edit] J’ai aussi supprimé « Login with Ajax« , ça a été un peu compliqué mais ça fonctionne.

A suivre …

Share

Accélérer WordPress #4 – Ressources statiques en cache

Suite …

Il reste à inviter le browser à mettre en cache les ressources statiques. Là je tremble un peu parce que l’histoire de la bouille du précédent m’obsède …

Je me lance : j’ajoute au .htacess les lignes suivantes, qui ne concernent que les principales ressources vraiment statiques :

# BEGIN Expire headers
ExpiresActive On
ExpiresDefault « access plus 0 seconds »
ExpiresByType image/jpg « access plus 2592000 seconds »
ExpiresByType image/jpeg « access plus 2592000 seconds »
ExpiresByType image/png « access plus 2592000 seconds »
ExpiresByType image/gif « access plus 2592000 seconds »
AddType image/x-icon .ico
ExpiresByType image/ico « access plus 2592000 seconds »
ExpiresByType image/icon « access plus 2592000 seconds »
ExpiresByType image/x-icon « access plus 2592000 seconds »
ExpiresByType text/css « access plus 300 seconds »
ExpiresByType text/javascript « access plus 2592000 seconds »
ExpiresByType application/javascript « access plus 2592000 seconds »
ExpiresByType application/x-javascript « access plus 2592000 seconds »
ExpiresByType application/x-shockwave-flash « access plus 2592000 seconds »
# END Expire headers

J’ai laissé les CSS en cache pendant 5 minutes, au moins pendant la phase de développement. Le résultat est épatant :3 requêtes seulement pour le repeat view, chargé en moins de 1 seconde

expire

Pour aller plus loin, il faudrait :

  • Utiliser un CDN pour charger plus vite les fichiers statiques
  • Mettre des commandes « Cache control-max-age »
  • Utiliser des images les plus petites possible (GIF) dans les articles
  • Supprimer les cookies pour les images

Je testerai ça bientôt et vous tiendrai au courant

Share

Accélérer WordPress #3 – Cache et gZip

Suite …

Je continue à lire sur les forums : « il faut utiliser un plugin de cache » et activer la compression gZip.

Cache

Je découvre qu’il y a 2 types de cache :

  • Le cache du navigateur de l’utilisateur, qui va stocker les fichiers déjà reçus pour les servir plus rapidement. Ca c’est pour quand l’internaute a déjà visité la page (repeat view)
  • Les fichiers mis en cache sur le serveur, pour un chargement plus rapide. Le principe est qu’au lieu de calculer à chaque fois la page à afficher, puis de l’envoyer  C’est cette page qui sera envoyée à chaque nouvel appel de la page. Ca impacte directement le first bit de la first view

Allez hop, c’est parti, je commence par ajouter « define(‘WP_CACHE’, true); » dans config.php. Ça ne sert pas à grand chose.

Donc il faut s’y coller : je vais installer un plugin de cache. W3 Total Cache m’a amusé pendant de longues heures, mais je n’ai pas réussi à le dompter : les utilisateurs connectés voyaient la bouille de quelqu’un d’autre à la place de la leur …. Pourtant, c’était une bonne piste puisque je suis arrivé à des résultats bluffants :

w3tc1,1 seconde pour « start render », c’est génial ! A noter que la page met 4,9 seconde à se charger complètement, mais ce n’est pas trop gênant : il y a déjà quelque chose à l’écran ! Ce qui prend tu temps, c’est l’image de fond (background-image) et le GIF animé, donc ce n’est pas de l’info très utile.

Et surtout, le repeat view : 1,3 secondes pour tout afficher ! Mais comme je l’ai dit, on voyait la bouille de l’internaute précédent … Les « pages statiques » HTML mises en caches n’étaient pas actualisées pour les « contenus dynamiques », et je n’ai pas réussi à corriger ça.

Un autre plugin de cache très populaire est WP super cache. Action !

Lui ne fait pas aussi bien puisqu’il lui manque la compression gZip et les « expire headers », mais au moins l’expérience utilisateur est préservée.

Compression gZip

J’ai ajouté au .htaccess une commande de compression des principales ressources statiques, images, css et js :

# BEGIN GZIP
<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE image/gif
AddOutputFilterByType DEFLATE image/jpg
AddOutputFilterByType DEFLATE image/jpeg
AddOutputFilterByType DEFLATE image/png
</ifmodule>

NB : il y a une explication très utile ici pour configurer le fichier .htaccess

Résultats

C’est pas mal du tout avec :

  • Start render = 1,5 secondes
  • Complete en 5 secondes
  • Et une réduction de la taille de la page à 650 kB (plus de 900 au départ)

gZipIl reste encore à mettre les ressources statiques en cache, à suivre …

Share

Accélérer WordPress #2 – Nettoyer les plugins et le header (JS et CSS)

Suite de l’épisode précédent

Regardons maintenant les résultats du test n°1, représentatif de l’ « expérience utilisateur » avec une dizaine de secondes avant de voir apparaître la page. La « waterfall view » nous indique :

waterfall

  • Qu’il faut 8,5 secondes pour calculer la page et renvoyer le « first bit »
  • Ensuite, 23 requêtes sont nécessaire avant l’affichage (incomplet) de la page. Ces 23 requêtes concernent le chargement des feuilles de style (CSS) et les scripts (JS) du thème et des plugins. En particulier on a les 2 « gros » : style.css (1,7 secondes) et jquery (1,9 secondes). Au total, + 2 secondes.
  • Le « start render » (ligne verte) commence à près de 11 secondes.

Je lis sur les forums :

  • Evitez les appels de fonctions, scripts JS, CSS inutiles dans le « header »
  • Compressez (minify) les .css et .js
  • chargez les scripts JS dans le footer quand c’est possible

Appels de fonctions, scripts, css inutiles dans le « header »

Là, pas de miracle : il faut aller dans le code du thème et décortiquer, élaguer, supprimer, simplifier … tout ce qui est exécuté dans le header (fichier header.php) du thème. Pour chacune des commandes qui précède </head> il faut aller regarder à quoi ça sert, si on peut le simplifier, voire le supprimer. C’est important puisque c’est ce qui fait le temps de calcul jusqu’au « first bit ».

Supprimer les plugins inutiles

Là, c’est plus compliqué, vu qu’ils sont tous « indispensables ». Mais un peu d’analyse de la valeur s’impose, en particulier pour les plugins qui simplifient la vie du développeur, mais n’apportent rien à l’utilisateur. Tiens, ça me rappelle quelque chose … Damien, féru de TOB dirait je crois « l‘activité de l’appareil« .

Par exemple, j’avais un plugin « widget on page » qui permet de … mettre des widgets dans une page. En fait, il suffit d’appeler les fonctions ad hoc au bon endroit, et on peut supprimer le plugin.

Aussi, j’avais un joli plugin pour faire « tourner » les images sur la page d’accueil : je l’ai remplacé par un gif animé (plus log à charger, mais APRES le « start render »).

Minify les CSS

Mon thème dispose de plusieurs CSS en cascade. Je les ai toutes mises bout à bout, et ensuite « minifiées » en ligne : http://refresh-sf.com/yui/.

Mon thème était développé avec les polices Google, 1 seconde pour les charger …  Un peu de boulot dans les CSS et c’est autant de gagné.

En revanche, je n’ai pas assemblé les CSS des autres plugins, au cas où je les mettrais à jour … ou si j’arrive à les supprimer.

Minify les JS

Là je n’ai rien réussi à faire

Chargez les scripts JS dans le footer

C’est très tentant, puisque ça reporte le chargement à plus tard. En fait, quand on regarde bien les JS sont chargées en temps masqué derrière la « grosse » jquery qui elle, de toutes façon, ne peut pas être déplacée. Mais bon, comme c’est sexy je l’ai fait. Dans le header.php ça donne :

volja_deregister_script('jquery'); volja_register_script('jquery', '//www.static.coach-abondance.com/js/jquery-1.7.1.min.js',false); volja_register_script('sg-jquery-ui', get_template_directory_uri() . '/js/jquery-ui-1.8.18.custom.min.js','','',true); volja_register_script('jquery.effects.core', get_template_directory_uri() . '/js/jquery.effects.core.min.js','','',true); volja_register_script('jquery.preloader', get_template_directory_uri() . '/js/jPreloader/jquery.preloader.js','','',true); volja_register_script('poise-form', get_template_directory_uri() . '/js/poise-form.js','','',true); volja_register_script('sg-height', get_template_directory_uri() . '/js/column-height.js','','',true); volja_register_script('sg-custom', get_template_directory_uri() . '/js/custom.js','','',true); volja_enqueue_script('jquery'); volja_enqueue_script('sg-jquery-ui'); volja_enqueue_script('jquery.effects.core'); volja_enqueue_script('jquery.preloader'); volja_enqueue_script('sg-height'); if (is_singular() ) { // AND _sg('Post')--->showComments() AND get_option('thread_comments')) {
volja_enqueue_script('poise-form');
volja_enqueue_script('comment-reply','','',true);
}
volja_enqueue_script('sg-custom');

Bluffant, isn’t it ? Ouais, bof, ne perdez pas de temps avec ça … C’est pas là que ça se joue.

[Edit] J’ai trouvé depuis beaucoup plus simple : dans functions.php du thème, ajouter ça :

/*
*    Automatically move JavaScript code to page footer, speeding up page loading time.
*/
remove_action(‘volja_head’, ‘volja_print_scripts’);
remove_action(‘volja_head’, ‘volja_print_head_scripts’, 9);
remove_action(‘volja_head’, ‘volja_enqueue_scripts’, 1);
add_action(‘volja_footer’, ‘volja_print_scripts’, 5);
add_action(‘volja_footer’, ‘volja_enqueue_scripts’, 5);
add_action(‘volja_footer’, ‘volja_print_head_scripts’, 5);

Tous les JS sont alors exécutés dans le footer. Magnifique !

Résultats

Tous ces efforts sont récompensés par une diminution sensible des temps de chargement : 4,4 secondes pour le first bit (-50%), le reste quasi inchangé. C’est donc bien dans le header qu’il faut bosser, les CSS et JS sont un plus.

header

A suivre …

Share

Accélérer WordPress #1 – Mesurer la vitesse de chargement

Une quinzaine de plugins, tous « indispensables », un thème pas génial mais trop de boulot d’en changer … et les pages mettent plus de 10 secondes à se charger. Inacceptable !

Je vous livre donc le fruit de mes recherches sur le web, les effets observés, ce qui marche, ou pas…

Comment connaître la vitesse de chargement ?

Il existe de nombreux outils en ligne, pour ma part j’utilise www.webpagetest.org avec les options suivantes :

  • Test location = ¨Paris
  • Browser = IE8 ou Chrome, ça ne fait pas une grosse différence. J’ai pris l’habitude de tester avec IE8 car la lecture des résultats est plus simple
  • Number of tests to run = 5
  • First and repeat view
  • Keep test private

Voilà à quoi ressemble le résultat pour le site www.coach-abondance.com.

debut

Les critères qui m’intéressent :

  • Start render = c’est le délai (médiane des 5 tests) que voit l’internaute entre le moment où il appelle la page et celui où elle commence à apparaître (même incomplète). Ici c’est 10,7 secondes pour le 1er appel du test n° 1. Une éternité !
  • Document complete = temps total d’affichage de la page. Ici 14,4 secondes, inacceptable.
  • Je regarde les mêmes valeurs pour la « repeat view » = temps de rechargement pour un internaute qui a déjà vu la page une fois. Près de 8 secondes, c’est un drame …

Bon, pas de doute, il y a du boulot !

[Edit] En complément j’utilise aussi www.GTMetrix.com, qui est beaucoup plus simple et donne d’autres ionformations, pas toujours cohérentes avec WebPageTest. En particulier l’analyse « YSlow » donne de bonnes idées.

Nous verrons aussi plus loin comment utiliser les autres informations.

A suivre …

 

Share