Logo_jQuery

Sizzle, la rénovation pour jQuery 1.8

Flattr this!

Je vous parlais il y a encore peu de la version 1.8 de jQuery qui est en cours de finition.

Mais comme vous, je suis un garçon curieux, juste en parler ne suffit pas, jeter un oeil non plus, il faut y mettre toute la tête. Donc on va regarder de près une des nouveautés clés de jQuery 1.8 : une nouvelle version de Sizzle !

Vous allez me dire "késako Sizzle ?". Sizzle, c'est le moteur de sélection qui fait l'essentiel de la magie de jQuery quand il est lié à cette fameuse méthode d'écriture dite "jQuery style". C'est Sizzle qui vous répond quand vous faites des trucs comme :

$(document)
$("form")
$("#votreDiv")

Oui, dans jQuery, il y a un vrai "moteur" et il nécessite parfois un petit coup de révision. Je vous propose donc ci-dessous une "traduction" de l'article dédié à ce nouveau Sizzle sur le blog de jQuery.

Une fonction de sélection compilée

L'analyseur syntaxique (parser en anglais) de sélection compile tout le sélecteur indiqué en une seule fonction contenant toutes celles permettant de gérer chaque partie du sélecteur. Cela signifie que pour chaque sélecteur (hormis ceux de position comme :first ou :eq(3)) n'ont besoin d'être testés qu'une seule fois. C'est de là que vient le gain majeur en rapidité du Nouveau Sizzle (ceci est une révolution! :p).

En bonus, Sizzle est capable de gérer un cache des fonctions compilées récemment. Ce cache a une taille maximale par défaut, mais qui peut être augmentée. Vous ne risquez donc à priori pas de dépassement mémoire en multipliant les sélecteurs. Ceci dit, c'est pas une raison pour oublier les règles d'optimisation de performances déjà énoncées. Le cache interne n'est pas une autorisation de faire de la merde avec.

Attention quand même : ces modifications n'influent en rien sur les sélecteurs "simples". C'est à dire ceux qui cherchent par ID, balises ou classes CSS puisque Sizzle ne fait que le raccourci vers les fonctions getElementByID, getElementsByTagName et getElementsByClassName. Ces sélecteurs étant totalement natifs, ils restent bien entendu les sélecteurs les plus rapides et sont donc à prioriser dans toutes vos recherches. Quand je vous disais que les règles jusqu'alors applicable continuent de devoir être respectées 😉

querySelectorAll et matchesSelector

Beaucoup de gens ont demandé pourquoi Sizzle est encore utilisé alors que tous les navigateurs modernes disposent de querySelectorAll et matchesSelector. Une partie de la réponse est déjà dans la phrase, tout comme seulement une partie des navigateurs le gèrent. Le rôle premier de jQuery reste d'assurer l'aplanissement des différences entre navigateurs. De plus, même parmi les navigateurs qui la gèrent, il y en a qui sont bogués sur cette fonctionnalité. L'équipe ne précisent pas lesquels mais assurent que Internet Explorer n'est pas le seul concerné.

De plus, ces fonctions natives des navigateurs ne savent pas gérer les extensions de sélecteur telles que la recherche [attr!=value]. Ce qui rend d'office Sizzle indispensable. Ceci dit, les performances ont été travaillées au maximum en faisant participer au maximum le moteur natif des navigateurs.

Validation des sélecteurs

La validation des sélecteurs peut poser des soucis. Être trop stricte peut être gênant, mais à l'inverse, être trop permissif peut produire des résultats relativement hasardeux. Et Sizzle est passé par les deux états. Pour couper à courts à toute discussion et finalement mettre tout le monde d'accord, la décision a été prise de s'en tenir aux spécifications du W3C. Ceci dit, ils continueront de maintenir des outils qui ont prouvé leur utilité tels que les sélecteurs complexes contenus dans le pseudo-sélecteur :not().

Fonctionnalité peut connue, Sizzle gère tous les espaces blancs (http://www.w3.org/TR/selectors/#whitespace) qui peuvent être nécessaires à une sélection. Les sauts de ligne, retours chariot et sauts de page sont systématiquement remplacés par des caractères adaptés (http://www.w3.org/TR/css3-syntax/#characters).

Combinaisons (espace, ~, >, +)

Comme pour tout, l'usage des combinaisons rend les choses plus compliquées. Sizzle a vu sa gestion des combinaisons franchement améliorée. Jusqu'à cette réécriture, on pouvait vite se retrouver avec un dépassement de pile (stack overflow) dans le cas de pages de grosses tailles contenant un arbre DOM relativement profond. Il ne faut pas oublier que chaque combinaison provoque un nuage de sélections qui sont ensuite combinées. Essayez de faire le calcul de tête, vous allez vite vous aussi être dépassé. Le nouveau Sizzle tient compte de ce risque.

Extensibilité

On va faire simple : l'API de Sizzle n'a pas été modifiée. Seule Sizzle.filter a dégagé. La façon la plus simple d'ajouter une capacité à Sizzle est de créer un pseudo sélecteur personnalisé. Vous serez d'autant plus aidé qu'avec le nouveau découpage dans la façon de traiter une sélection par compilation de fonctions vous donnera plus d'informations.

Voilà l'exemple avec l'implémentation du sélecteur :not :

var not = function (selector, context, isXml) {
    var matcher = Sizzle.compile(selector, context, isXml);
    return function (elem) {
        return !matcher(elem);
    };
};
// fn.sizzleFilter is set to true to indicate that not is a function that will
// return a function for use by the compiler and should be passed
// the pseudo argument, the context,
// and whether or not the current context is xml.
// If this property is not set,
// adding pseudos works similar to past versions of Sizzle
not.sizzleFilter = true;
Sizzle.selectors.pseudos.not = not;

Sizzle.compile est publique, du coup, vous pouvez en profiter pour pré-compiler vos propres sélecteurs. Cette pré-compilation évite que celle-ci soit faite à chaud pendant une sélection et augmentera donc la vitesse de réponse de vos sélecteurs. Si vous appelez .compile() avec votre sélecteur et le contexte comme ceci :

Sizzle.compile(“mon>sélecteur>super>:compliqué(toto)”, document);

Il sera ajouté au cache. La taille du cache peut être modifiée en changeant la valeur de Sizzle.selectors.cacheLength.

A noter : Dans la majorité des cas, pas besoin d'utiliser le cache à la main puisque Sizzle gère un cache des sélecteurs récemment compilés.

Flattr this!

A propos de Mathieu

Ingénieur développeur web dans la vente par correspondance B2B, adepte de nouvelles technologies et d'innovation. Vous pouvez aussi me retrouver sur Twitter @mathrobin
Cette entrée a été publiée dans jQuery, avec comme mot(s)-clef(s) , , , . Vous pouvez la mettre en favoris avec ce permalien.

Articles liés