Astuces de Webmaster

20 mars 2013

Chargement Asynchrone Javascript pour les liens ou les images

Je me suis fait un petit plaisir en développant un petit bout de code javascript permettant de charger de façon asynchrone un lien (ce qui permet de le rendre invisible aux moteurs de recherche), ou une image (ce qui évite qu’elle soit dans le chemin critique de chargement).

Charger des images en asynchrone, c’est notamment utile pour les images pour ce qui concerne les images cachées au chargement ou qui n’ont pas grande valeur ajoutée (rollover de menu, merchandising, etc.) contrairement à d’autres (logo, photos produits, etc.)

Charger des liens en asynchrone évite aux moteurs de crawler trop d’URLs et donc de se concentrer sur les vraies pages à référencer, ce qui évite de trop diluer le page rank.

Pour voir ce que cela donne, n’hésitez pas à regarder le site de Menlook, le spécialiste de la Mode Homme (la boîte pour laquelle je bosse) ;-) vous verrez des éléments qui se chargent en asynchrone, notamment les images du menu (rollover), et certains liens à gauche dans les catégories.

Pour utiliser ma méthode, vous créez vos liens ainsi en PHP :

 PHP |  Copier le code |? 
1
2
<span dataOBF="<?php echo base64_encode('http://www.monlien.com'); ?>" class="maclass">Mon texte de lien</span>
3
<span dataOBFimg="<?php echo base64_encode('/path/to/image.jpg'); ?>" alt="Mon Alt" />
4

ou avec Smarty :
 Smarty |  Copier le code |? 
1
2
<span dataOBF="{$product.link|base64_encode}" class="maclass">{l s='Plus d\'infos'}</span>
3
<span dataOBFimg="{$urlImage|base64_encode}" alt="Mon Alt" />
4

et cela sera remplacé automatiquement une fois la page chargée (après le reste du contenu synchrone)
Télécharger le fichier avec tout le JavaScript nécessaire (tout le JS ci-dessous s’y trouve, c’est tout ce dont on a besoin)

 Javascript |  Copier le code |? 
01
02
		var dataobf=function() {
03
			// for links
04
			$('span').each(function(index, value){
05
				if($(this).attr('dataOBF')) {
06
					var url = base64_decode($(this).attr('dataOBF'));
07
					var tClass = null;
08
					var tTitle = null;
09
					var tId = null;
10
					var tStyle = null;
11
					if($(this).attr('class')) { var tClass = ' class="'+$(this).attr('class')+'"'; }
12
					if($(this).attr('title')) { var tTitle = ' title="'+$(this).attr('title')+'"'; }
13
					if($(this).attr('id')) { var tId = ' id="'+$(this).attr('id')+'"'; }
14
					if($(this).attr('style')) { var tStyle = ' style="'+$(this).attr('style')+'"'; }
15
						$(this).replaceWith($('<a href="'+url+'" '+tClass+' '+tTitle+' '+tId+' '+tStyle+'>' + this.innerHTML + '</a>'));
16
				}
17
			});
18
			// for img (after load)
19
			$('span').each(function(index, value){
20
				if($(this).attr('dataOBFimg')) {
21
					var url = base64_decode($(this).attr('dataOBF'));
22
					var tClass = null;
23
					var tTitle = null;
24
					var tAlt = null;
25
					var tId = null;
26
					var tStyle = null;
27
					if($(this).attr('class')) { var tClass = ' class="'+$(this).attr('class')+'"'; }
28
					if($(this).attr('alt')) { var tAlt = ' alt="'+$(this).attr('alt')+'"'; }
29
					if($(this).attr('title')) { var tTitle = ' title="'+$(this).attr('title')+'"'; }
30
					if($(this).attr('id')) { var tId = ' id="'+$(this).attr('id')+'"'; }
31
					if($(this).attr('style')) { var tStyle = ' style="'+$(this).attr('style')+'"'; }
32
						$(this).replaceWith($('<img src="'+url+'" '+tClass+' '+tTitle+' '+tAlt+' '+tId+' '+tStyle+' />'));
33
				}
34
			});
35
			$('a').each(function(index, value){
36
				if($(this).attr('dataOBF')) {
37
					//alert(base64_decode($(this).attr('dataOBF')));
38
					$(this).attr('href', base64_decode($(this).attr('dataOBF')));
39
				}
40
			});
41
		}
42
		$(document).ready(function() {
43
			dataobf();
44
		});
45

 Javascript |  Copier le code |? 
01
02
		function base64_decode (data) {
03
		  // http://kevin.vanzonneveld.net
04
		  // +   original by: Tyler Akins (http://rumkin.com)
05
		  // +   improved by: Thunder.m
06
		  // +      input by: Aman Gupta
07
		  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
08
		  // +   bugfixed by: Onno Marsman
09
		  // +   bugfixed by: Pellentesque Malesuada
10
		  // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
11
		  // +      input by: Brett Zamir (http://brett-zamir.me)
12
		  // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
13
		  // *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
14
		  // *     returns 1: 'Kevin van Zonneveld'
15
		  // mozilla has this native
16
		  // - but breaks in 2.0.0.12!
17
		  //if (typeof this.window['atob'] == 'function') {
18
		  //    return atob(data);
19
		  //}
20
		  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
21
		  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
22
			ac = 0,
23
			dec = "",
24
			tmp_arr = [];
25
 
26
		  if (!data) {
27
			return data;
28
		  }
29
 
30
		  data += '';
31
 
32
		  do { // unpack four hexets into three octets using index points in b64
33
			h1 = b64.indexOf(data.charAt(i++));
34
			h2 = b64.indexOf(data.charAt(i++));
35
			h3 = b64.indexOf(data.charAt(i++));
36
			h4 = b64.indexOf(data.charAt(i++));
37
 
38
			bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
39
 
40
			o1 = bits >> 16 & 0xff;
41
			o2 = bits >> 8 & 0xff;
42
			o3 = bits & 0xff;
43
 
44
			if (h3 == 64) {
45
			  tmp_arr[ac++] = String.fromCharCode(o1);
46
			} else if (h4 == 64) {
47
			  tmp_arr[ac++] = String.fromCharCode(o1, o2);
48
			} else {
49
			  tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
50
			}
51
		  } while (i < data.length);
52
 
53
		  dec = tmp_arr.join('');
54
 
55
		  return dec;
56
		}
57

D’un point de vue SEO un peu plus poussé, j’ai eu le retour très légitime suivant auquel j’ai répondu :

7 décembre 2012

Optimiser les performances Prestashop, comment accélérer Prestashop ?

Après avoir longtemps travaillé à optimiser Prestashop, voici rassemblé tout ce qui devrait vous permettre d’améliorer vos performances et faire accélérer cet outil. Du plus simple au plus complexe.

Grosse checklist, prenez ce que vous voulez dedans !

Si vous pensez à autre chose ou que vous voulez compléter la liste, un petit mot dans les commentaires et hop !

Si besoin d’aide, contactez-moi !

  1. Dans préférences > performances, Activer le cache smarty (tout le monde l’a fait, mais ne sait on jamais pour les newbies)
  2. Désactiver le force-compile (même endroit)
  3. Activer l’option « minify » (même endroit)
  4. créer des sous-domaines pour les médias (même endroit). pour ce faire, si vous ne voulez pas un serveur à part, vous pouvez simplement diriger des sous-domaines vers le même vhost sur votre serveur, cela permet de multiplier le nombre de téléchargements parallèles par le navigateur). Avoir un serveur à part pour les médias vous permettra de mieux servir tous les médias
  5. Définir le cache-expire pour les médias (pour les détails, lire cet article)
  6. charger les images les contenus les moins importants après le chargement de la page (document.ready) pour éviter que le contenu le moins utile (et parfois invisible s’il est dans des menus rollover) ralentisse le temps de chargement initial
  7. Tracer les requêtes différentes de la même page (en regroupant par type de requête sans prendre en compte les variables qui s’y trouvent), en faisant un petit override de la classe mysql, et identifier les doublons
  8. Tracer les temps de calcul des hooks (fonction hookexec) pour identifier les hooks (souvent des modules qu’on rajoute) qui ralentissent le plus ; désactiver ceux qui ne sont pas vraiment utiles ou les optimiser
  9. Créer un cache sur toutes les parties statiques et pourquoi pas sur l’intégralité des pages (attention à la quantité et au poids du cache créé ! il peut être bon de limiter). Pourquoi ne pas créer le cache sur la page intégrale et charger en ajax par dessus les éléments dynamiques (mon nom, mon panier, mes favoris, etc.)
  10. Envisager de faire évoluer votre hébergement : en premier lieu ajouter un serveur de médias, puis de base de données, si votre site est bien paramétré ajouter un serveur spécialement pour le cache, envisager de découpler votre serveur Apache+PHP en un serveur Apache/Nginx d’un côté et un serveur PHP de l’autre, etc. Attention : Prestashop gère les sessions en cookie, le load balancing d’un frontal à un autre ferait perdre les sessions à vos utilisateurs, il faut donc gérer tout load balancing en mode IP !

Si vous voyez d’autres choses permettant l’optimisation de Prestashop, ou si vous voulez que je détaille une partie, n’hésitez pas, j’ai déjà rajouté quelques points grâce aux commentaires !

Pour me contacter, vous pouvez passer par mon profil Google+ ;-)

26 juillet 2012

Enlever les cookies des appels d’images – Optimisation

Vous avez sans doute déjà vu si vous utilisez PageSpeed la recommandation suivante :

Serve static content from a cookieless domain

Cela signifie que vos images se trouvant sur le même nom de sous-domaine que votre site, le navigateur transmet à chaque appel d’image dans les entêtes les cookies du site, en cas de besoin.

Une solution simple consiste à ajouter ceci dans le htaccess

 Apache configuration |  Copier le code |? 
1
<IfModule mod_headers.c>
2
	<FilesMatch "\\.(js|css|jpg|png|jpeg|gif|css)$">
3
		RequestHeader unset Cookie
4
		Header unset Set-Cookie
5
		Header set Cache-Control "max-age=86400"
6
	</FilesMatch>
7
</IfModule>

De cette manière, pour chaque appel de fichier média, les cookies ne seront pas traités.

Il est intéressant d’aller plus loin. Si vous pouvez-faire en sorte de rediriger un sous-domaine sur le même nom de domaine que le www, vous pouvez créer un sous-domaine spécifique pour les médias.

Ainsi, il vous suffit par exemple sur Apache d’éditer la configuration et de rajouter une ligne comme suit dans la configuration de votre nom de domaine (la plupart du temps dans le fichier /etc/apache2/sites-available/nomDuSite)

 Apache configuration |  Copier le code |? 
1
ServerAlias media.monsite.com

il faut ensuite redémarrer apache pour prise en compte (commande ssh)

 shell |  Copier le code |? 
1
/etc/init.d/apache2 restart

Ceci aura pour effet de diriger le sous-domaine « media » vers le même emplacement que le domaine principal (« www ») et du coup, vous pourrez appeler vos images anciennement pointant vers www.monsite.com/image.jpg via media.monsite.com/image.jpg

Si vous définissez vos cookies au niveau du sous-domaine (ex pour PHP : 5e argument de la fonction setcookie), ils ne seront alors pas transmis lors des appels vers le sous-domaine « media ».

Le htaccess défini plus haut sera par ailleurs pris en compte, ce qui permettra de ne pas prendre en compte tout cookie envoyé de toute façon.

Articles plus anciens »

Romain BOYER ©2014 - Contact : boyer Arobase romain Point biz - Profil sur LinkedIn - Profil sur Google+