performance,javascript,optimisation

JavaScript, les bonnes pratiques : optimiser vos scripts (2/2)

Le 2 décembre 2010 par Maxime dans Conception web.


Nous avons discuté dans un article précédant des différentes optimisations de base que l’on peut apporter facilement à ses scripts js. Attaquons maintenant des notions un peu plus techniques, en décortiquant les points sensibles du JavaScript en termes de performance.On pourra alors déceler les erreurs à éviter et les pratiques à appliquer pour aller plus loin dans l’optimisation de nos scripts.

Une histoire de portée

La portée des variables (ou scope), c’est leur domaine d’existence. Une variable peut être globale à tout un script ou être uniquement locale à une fonction. En JavaScript, on déclare une variable locale grâce au mot-clé var. Sans ce mot-clé, la variable sera considéré comme globale.

Comment JavaScript va-t-il chercher en mémoire les valeurs allouées aux variables que l’on a déclarées ? Il faut savoir que chaque fonction appelée crée un environnement de variable, qui sera détruit à la fin de la fonction. Ainsi, si une fonction est appelée dans une autre, un contexte d’exécution est encore créé, ainsi de suite, créant une chaîne. Plus la variable que l’on veut accéder est loin dans la chaîne, plus de temps mettra la résolution de la valeur. Une variable globale par exemple, est accessible partout, ce qui la contraint donc d’être en bout de chaîne. La résolution d’une variable globale sera donc plus lente que celle d’une variable locale.

On peut donc en tirer des conclusions pour optimiser nos scripts. Tout d’abord, essayez de n’utiliser qu’un minimum de variables globales. Précédez systématiquement vos variables du mot-clé var pour les déclarer locales, et enlever le par la suite si c’est vraiment nécessaire. Une erreur que l’on peut faire souvent : la déclaration de la variable d’incrémentation dans une boucle for. Si nous ne spécifions pas var, la variable sera considérée comme globale !

for(var i=0 ; i<10 ; ++i) { }

Si vous devez accéder plusieurs fois à une variable qui est en dehors du contexte de la fonction, et en particulier une variable globale, il serait judicieux de la stocker dans une variable locale, et réutiliser celle-ci ensuite. Par exemple, lors d'appel successif à document ou window.

var divs = document.getElementsByTagName('div');
var pgfs = document.getElementsByTagName('p');
var imgs = document.getElementsByTagName('img');

var doc = document;
var divs = doc.getElementsByTagName('div');
var pgfs = doc.getElementsByTagName('p');
var imgs = doc.getElementsByTagName('img');

Pour ces mêmes raisons d'accès au scope, il est mieux d'éviter les structures with et catch qui, même si elles peuvent être pratiques, créent un autre contexte d'exécution, et éloignent vos variables d'un cran.

Accès aux données

Il y a différentes sortes de stocker de l'information en js. Vous pouvez stocker une valeur litérale (int, string, …) dans une variable. Mais vous pouvez également utiliser des structures de données plus complexes comme les tableaux (array) ou les objets (object).

Il faut savoir qu'accéder à un item d'un array ou d'une propriété d'un objet est plus coûteux qu'un simple accès à une variable contenant une valeur litérale. Si vous accéder plusieurs fois à la même information, stockez-la dans une variable locale, pour de meilleures performances.

Aussi, plus la profondeur d'un tableau ou d'un objet est grande, plus le temps de résolution sera important. Essayez donc d'étaler vos données plutôt à « l'horizontale ». Bien sûr, il faudra doser cette optimisation pour garder un code lisible et maintenable.

var infos = {
   personne : ['prenom' => 'Be','nom' => 'wype','age' => 1],
   adresse : 'ici',
   fonction : 'blog'
}
if(infos.personne.nom.length == 4) {
   connexion(infos. personne.nom) ;
   enregistrement(infos. personne.nom) ;
   affichage(infos. personne.prenom+' '+infos. personne.nom+', '+infos. fonction) ;
}

var infos = {
   prenom : 'Be',
   nom : 'wype'
   age : 1,
   adresse : 'ici',
   fonction : 'blog'
}
var nom = infos.personne.nom;
if(nom == 4) {
   connexion(nom) ;
   enregistrement(nom) ;
   affichage(infos.prenom+' '+nom+', '+infos.fonction) ;
}

Ce changement est bénéfique dès lors que l'on accède plus d'une fois à la même valeur d'un tableau ou d'un objet. Le gain est bien sûr multiplié si le code contient des boucles.

surcouche js repaint

Repaint et Reflow

Commençons par définir ces deux termes, je vois que certains froncent les sourcils.

Repaint
C'est quand le navigateur redéfinit l'apparence d'un objet. Un changement de style css sur des propriétés tels que background, color, border-color... Cette opération est assez lente, car le navigateur doit réafficher l'élément modifié.
Reflow
Cette fois, c'est la forme de l'objet que le navigateur redéfinit. Lorsque l'on ajoute ou l'on enlève un élément du DOM par exemple. Il survient aussi avec des changements de style sur des propriétés tels que width, height, display… Un reflow d'un élément entraîne le reflow de ses enfants, ainsi que celui de ses ancêtres dans le DOM. Finalement, lors d'un reflow, le navigateur doit souvent réafficher tout le DOM, c'est donc une opération très lente.

Les interactions avec l'utilisateur sont l'un des intérêts principaux du JavaScript, il n'est donc pas question d'essayer de limiter les changements de DOM, ou les animations. Par contre, on peut optimiser nos scripts en regroupant ces changements pour limiter le nombre de repaint et reflow. Comme nous l'avons vu dans l'article précédant, n'hésitons pas à déléguer au css ces changements de style. Dans l'exemple suivant, nous passons ainsi de 3 à 1 seul reflow.

var monDiv = document.getElementById('monDiv') ;
monDiv.style.width = '100px';
monDiv.style.height = '200px';
monDiv.style.margin = '10px 0px 15px 5px';

var monDiv = document.getElementById('monDiv') ;
monDiv.className = 'maClasseCss';

De même pour les ajouts ou suppression d'élément du DOM. Regroupez par exemple les éléments que vous voulez ajouter au DOM et n'appelez qu'une seule fois la fonction append.

A votre tour

Avec tout ce que nous avons vu ensemble, vous avez déjà une belle palette d'optimisation à vos scripts. L'utilisation de librairies javascript comme Prototype ou jQuery aide grandement l'utilisation de javascript et accélère la rapidité de développement. Bien entendu, cette surcouche rajoute de la complexité dans les algorithmes déployés et la vitesse en prend un coup. Encore une fois, de bons réflexes pour optimiser l'utilisation de ces framework js sont à prendre pour trouver le bon compromis entre optimisation des performances, maintenabilité et temps de codage. Ces précieux dixièmes de seconde vous paraitront peut-être stupides, mais ils ne le seront certainement pas pour votre visiteur en 512k sur IE 6... Bon ok, lui il abuse peut-être. Mais l'intérêt d'optimiser ne va pas disparaître avec l'augmentation des performances des machines clientes. On ne peut ignorer aujourd'hui la volonté de Google de promouvoir l'internet rapide : on commence à parler de bonus de référencement pour les sites dont le temps de chargement est optimisé. Qu'en pensez-vous ?


Flux RSS de design, referencement, actus internet - Bewype

Recevez les articles tout chauds sortis du four !
Inscrivez-vous à notre flux RSS

Partager - Faîtes découvrir le blog Bewype - conception site internet et logique entrepreneuriale


Jeter un oeil sur les autres articles : design graphique, actu web et marketing seo

Jeter un oeil sur les autres articles : , ,

JavaScript, les bonnes pratiques : mise en place

javascript-js-jquery

JavaScript, les bonnes pratiques : optimiser vos scripts (1/2)

optimisez-vos-performances

Vos commentaires sur JavaScript, les bonnes pratiques : optimiser vos scripts (2/2)

(5) performance,javascript,optimisation - Réagissez !
Marius, Tennis en live

12 décembre 2010 à 12 h 47 min

Merci pour votre tutorial, vous avez perdu beaucoup de l’ecrire. Est-que vous pouvez pare un avec le PHP? Merci


Maxime

12 décembre 2010 à 15 h 34 min

Je ne suis pas sûr de vous avoir compris ; je passe beaucoup de temps à écrire mes articles, mais je pense que l’on gagne à partager ce que l’on sait ;-)
Et oui, il y aura des articles sur PHP, Ruby On Rails, HTML, CSS…


Mathieu, Stylo

7 janvier 2011 à 14 h 33 min

Et 2 choses chose très importantes que j’ai notées dans mes expériences.

Tant que possible, charger les JS à la FIN des pages et, si possible, tout charger en un seul fichier.

jQuery est juste une plaie en terme de volume, avec ou sans CDN.


Maxime

8 janvier 2011 à 12 h 13 min

Exact, un seul fichier pour n’avoir qu’une requête HTTP et à la fin pour charger tout le reste avant et avoir l’impression que cela charge plus vite.

Personnellement, je compresse mon script en même temps que la librairie jquery dans un seul fichier. Certains préfèrent charger jQuery séparément, via CDN justement. Les performances que l’on gagne à utiliser un CDN, on le perd avec le « DNS Lookup », c’est-à-dire le temps que met le navigateur pour se connecter à un autre nom de domaine (puisque CDN = autre serveur). Les CDN sont surtout utiles à mon avis pour les sites utilisant plusieurs librairies ressources partagées.


assistance informatique

28 juin 2011 à 0 h 00 min

Merci pour ces quelques astuces, c’est peut etre mieux que du css pas toujours compatible tout navigateurs


Ajouter votre commentaire sur Optimisations avancées des performances en javascript