Fermer

juin 18, 2018

Sélecteurs d'ID et autres mythes –


Dans le scénario typique d'aujourd'hui, où le site Web moyen livre 500 Ko de JavaScript gzip et 1,5 Mo d'images, fonctionnant sur un appareil Android de milieu de gamme via 3G avec un temps d'aller-retour de 400 ms, la performance du sélecteur CSS est le moindre de nos problèmes. ] Cependant, il y a quelque chose à dire sur le sujet, en particulier pour éliminer certains des mythes et légendes qui les entourent. Alors, allons-y.

Les bases de l'analyse CSS

Tout d'abord, pour aller sur la même page, cet article ne traite pas de la performance des propriétés et des valeurs CSS. Ce que nous couvrons ici, c'est le coût de la performance des sélecteurs eux-mêmes. Je vais me concentrer sur le moteur de rendu de Blink, en particulier sur Chrome 62.

Les sélecteurs peuvent être divisés en quelques groupes et (grosso modo) triés du moins cher au plus cher:

rank type exemple
1. ID #classID
2. classe .classe
3. Tag div
4. Frères du secondaire général et voisin div ~ a div + a
5. Enfant et descendant div > a div a
6. universel *
7. Attribut [type="text"]
8. Pseudo-classes et éléments a: premier-type a: hover

Cela signifie-t-il que vous ne devriez utiliser que des identifiants et des classes? Eh bien pas vraiment. Ça dépend. Tout d'abord, couvrons comment les navigateurs interprètent les sélecteurs CSS.

Les navigateurs lisent CSS de droite à gauche. Le sélecteur le plus à droite dans un sélecteur composé est connu sous le nom de sélecteur . Ainsi, par exemple, dans #id .class> ul a le sélecteur de clé est a . Le navigateur correspond d'abord à tous les sélecteurs de clé. Dans ce cas, il trouve tous les éléments de la page qui correspondent au sélecteur . Il trouve ensuite tous les ul éléments sur la page et filtre les a vers les éléments qui sont des descendants de ul s – et ainsi de suite jusqu'à ce qu'il atteigne le sélecteur le plus à gauche.

Par conséquent, plus le sélecteur est court, mieux c'est. Si possible, assurez-vous que le sélecteur de clé est une classe ou un ID pour le garder rapide et spécifique.

Mesure de la performance

Ben Frain a créé une série de tests pour mesurer la performance du sélecteur 2014. Le test consistait en un énorme DOM comprenant 1000 éléments identiques, et mesurant la vitesse nécessaire à l'analyse de divers sélecteurs, allant des identifiants à des sélecteurs complexes très longs et complexes. Ce qu'il a trouvé, c'est que le delta entre le sélecteur le plus lent et le plus rapide était ~ 15ms

Cependant, c'était en 2014. Les choses ont beaucoup changé depuis, et les règles de mémorisation sont presque inutiles dans le paysage changeant des navigateurs. . Rappelez-vous toujours de faire vos propres tests, surtout quand vous êtes performant.

Je suis allé faire mes propres tests, et pour cela j'ai utilisé le test de Paul Lewis mentionné dans Paul Irish , encore alambiquée " sélecteurs de quantité ":

Ces sélecteurs sont parmi les plus lents possibles. ~ 500 plus lent que quelque chose de sauvage comme "div.box:not(:empty):last-of-type .title". La page de test http://jsbin.com/gozula/1/quiet

Le test a été augmenté un peu, à 50000 éléments, et vous pouvez le tester vous-même . J'ai fait une moyenne de 10 courses sur mon MacBook Pro 2014, et ce que j'ai eu était le suivant:

Sélecteur Temps de requête (ms)
div 4.8740
.box 3.625
.box> .title 4.4587
.box .title 4.5161
.box ~ .box [19659010] 4.7082
.box + .box 4.6611
.box: dernier-né 3.944
.box: nth-of-type (2n - 1) 16.8491
.box: non (: dernier-né) 5.8947
.box: non (: vide): dernier-type-type 8.0202
.box: nième-dernier-enfant (n + 6) ~ div 20.8710

Les résultats varieront bien sûr selon que vous utilisiez querySelector ou querySelectorAll et le nombre de nœuds correspondants sur la page, mais querySelectorAll se rapproche du cas d'utilisation réel de CSS, qui est Même dans un cas extrême, avec 50000 éléments à faire correspondre, et en utilisant des sélecteurs vraiment insensés comme le dernier, nous trouvons que le plus lent est ~ 20ms, tandis que le plus rapide est la classe simple à ~ 3.5ms. Pas vraiment une différence. Dans un DOM réaliste, plus "apprivoisé", avec environ 1000-5000 nœuds, on peut s'attendre à ce que ces résultats baissent d'un facteur 10, les amenant à des vitesses d'analyse inférieures à la milliseconde.

Ce que nous pouvons voir de ce test est que cela ne vaut pas vraiment la peine de s'inquiéter des performances du sélecteur CSS. N'en faites pas trop avec des pseudo-sélecteurs et des sélecteurs vraiment longs. Nous pouvons également voir comment Blink s'est amélioré au cours des deux dernières années. Au lieu du ralentissement indiqué ~ 500x pour un "sélecteur de quantité" ( .box: nième-dernier-enfant (n + 6) ~ div ) comparé à un "sélecteur de folie" ( .box: pas (: vide): dernier-type .title ), on ne voit qu'un ralentissement ~ 1.5x. C'est une amélioration incroyable, et nous ne pouvons qu'espérer que les navigateurs s'amélioreront, rendant la performance du sélecteur CSS encore moins percutante.

Cependant, vous devriez s'en tenir aux classes autant que possible, et adopter une sorte d'espace de noms comme BEM, SMACSS ou OOCSS, car il aidera non seulement la performance de votre site Web mais aidera grandement à la maintenabilité du code. Les sélecteurs de composés surqualifiés, en particulier lorsqu'ils sont utilisés avec des sélecteurs d'étiquette et universels – tels que .header nav ul> li> .inner – sont extrêmement fragiles et source de nombreuses erreurs imprévues. Ils sont aussi un cauchemar à maintenir, surtout si vous héritez du code de quelqu'un d'autre.

La qualité sur la quantité

Un plus gros problème de simplement avoir des sélecteurs coûteux est d'en avoir beaucoup. C'est ce qu'on appelle «le ballonnement du style», et vous avez probablement déjà beaucoup vu le problème. Des exemples typiques sont des sites qui importent des frameworks CSS complets comme Bootstrap ou Foundation, en utilisant moins de 10% du CSS transféré. Un autre exemple est vu dans les vieux, projets jamais refactorisés dont CSS a dévolu dans, comme j'aime les appeler, "Chronological Style Sheets" – CSS avec une tonne de classes ajoutées à la fin du fichier que le projet a changé et grandi , maintenant ressemblant plus à un jardin envahi par les mauvaises herbes.

Non seulement un gros fichier CSS prend plus de temps à transférer, (et le réseau est le plus grand goulot d'étranglement dans la performance du site Web), mais ils prennent aussi plus de temps. analyser. En plus de construire le DOM à partir de votre HTML, le navigateur doit construire un CSSOM (CSS Object Model) pour le comparer avec le DOM et faire correspondre les sélecteurs.

Alors, gardez vos styles fins et secs, n'incluez pas tout et l'évier de la cuisine, chargez ce dont vous avez besoin et quand vous en avez besoin, et utilisez UNCSS si vous voulez.

Si vous voulez en savoir plus sur la façon dont les navigateurs analysent CSS, L'article de Nicole Sullivan sur Webkit L'article d'Ilya Grigorik sur la façon dont Blink le fait ou l'article de Lin Clark sur le nouveau moteur Stylo CSS de Mozilla

The Elephant in the Room: Style Invalidation

Ce que nous avons couvert jusqu'ici est correct, mais nous n'avons discuté que d'une seule passe de rendu. Les sites Web d'aujourd'hui ne sont plus des documents statiques, mais ressemblent à des applications avec lesquelles les utilisateurs peuvent interagir.

Cela complique les choses, car l'analyse CSS n'est qu'une étape dans le pipeline de rendu du navigateur. Voici une vue orientée vers le rendu de la façon dont un navigateur rend une seule image à l'écran (source: Google ):

 Le pipeline de rendu du navigateur

Nous ne serons pas en passant par les performances JavaScript et la composition, mais se concentrera plutôt sur l'analyse syntaxique en partie pourpre et la disposition des éléments.

Après avoir construit le DOM et le CSSOM, le navigateur doit combiner les deux dans un arbre de rendu. l'écran. Dans cette étape, le navigateur doit comprendre le CSS calculé pour chaque élément correspondant. Vous pouvez le voir vous-même dans le panneau Elements> Styles des outils de développement. Il faut tous les styles correspondants, la cascade et les styles d'agent utilisateur spécifiques au navigateur pour construire le CSS final calculé pour l'élément.

Il peut ensuite passer à l'étape de mise en page (redistribution), où il calcule le géométrie, et construit le modèle de boîte de la page, en plaçant chaque élément sur sa position respective sur la fenêtre. La mise en page est la partie la plus exigeante en termes de calcul de ce processus

Enfin, le navigateur convertit chaque noeud de l'arbre de rendu en pixels réels sur l'écran de la couche de peinture.

Maintenant, que se passe-t-il? en changeant des classes sur la page, en ajoutant ou en supprimant des nœuds, en modifiant certains attributs, ou en jouant avec le HTML ( ou les feuilles de style elles-mêmes )

styles et le navigateur doit invalider tout dans l'arborescence des sélecteurs correspondants. Alors que les navigateurs d'aujourd'hui sont beaucoup plus intelligents, il arrivait que si vous changiez une classe sur l'élément body tous les éléments descendants avaient besoin de recalculer leurs styles calculés.

Une façon d'éviter cela Le problème consiste à réduire la complexité de vos sélecteurs. Au lieu d'écrire #nav> .list> li> a utilisez un seul sélecteur, comme .nav-link . De cette façon, vous réduisez la portée de l'invalidation de style, puisque si vous modifiez quoi que ce soit à l'intérieur du #nav vous ne déclenchez pas de recalculs pour le noeud entier.

comme le nombre d'éléments invalidés. Soyez spécifique avec votre CSS. Gardez cela à l'esprit surtout pendant les animations, où le navigateur n'a que ~ 10ms pour faire tout le travail requis.

Si vous voulez aller aux détails de l'invalidation de style, je vous recommande de lire Invalidation de style dans Blink

Conclusion

Pour résumer, vous ne devriez pas vous inquiéter de la performance du sélecteur, à moins que vous vraiment ne pardonniez. Alors que le sujet faisait fureur en 2012, les navigateurs ont beaucoup beaucoup plus rapide et plus intelligents depuis. Même Google ne s'en inquiète plus. Si vous consultez la page Page Speed ​​Insights de Google vous ne verrez pas la règle "Utiliser des sélecteurs CSS efficaces" qui a été supprimée en 2013.

Au lieu de cela, concentrez-vous sur CSS maintenable et lisible. Vos collègues et votre futur moi vous en seront reconnaissants. Essayez d'optimiser la distribution CSS en incluant uniquement les styles utilisés. Et après cela, apprendre à connaître le pipeline de rendu. Contrairement aux sélecteurs, les styles eux-mêmes peuvent être coûteux, et la différence entre un site janky et un site lisse peut souvent être trouvée dans la façon dont le CSS est implémenté.

note: faites toujours vos propres tests.

Ne croyez pas seulement ce que quelqu'un a écrit sur Internet il y a quelques années. Le paysage change radicalement et à un rythme incroyable. Ce qui est pertinent aujourd'hui peut devenir obsolète plus tôt que vous ne le savez




Source link