Que faire lorsque CSS bloque l'analyse des pages?

Récemment, j'ai effectué un audit d'un site et preload/polyfillsuis tombé sur un schéma que j'ai déjà vu avec plusieurs clients. Aujourd'hui, l'utilisation de ce modèle auparavant populaire n'est pas recommandée. Cependant, il est utile de l'examiner afin d'illustrer l'importance d'une utilisation prudente du mécanisme de préchargement des documents par les navigateurs Web. Il est également intéressant car il vous permet de démontrer un exemple réel de la façon dont l'ordre des éléments dans un document peut affecter les performances (c'est ce qui est discuté dans ce merveilleux article de Harry Roberts). Le matériel, dont nous publions la traduction aujourd'hui, est consacré à l'analyse de situations dans lesquelles une manipulation incorrecte et intempestive des ressources CSS affecte les performances des pages Web.





Ă€ propos de loadCSS


Je suis un grand fan du groupe Filament - ils sortent une quantité incroyable de grands projets. De plus, ils créent constamment des outils précieux et les partagent dans le but d'améliorer le Web. L'un de ces outils est loadCSS , qui a longtemps été l'outil même que j'ai recommandé à tout le monde d'utiliser pour charger des ressources CSS non critiques.

Bien que cela ait maintenant changé (et que le Groupe Filament a publié un excellent article sur ce que ses employés préfèrent utiliser ces jours-ci), je constate toujours, lorsque j'audite des sites, comment ils l' loadCSSutilisent en production.

L'un des modèles que j'ai rencontrés est le modèlepreload/polyfill. En utilisant cette approche, tous les fichiers avec des styles sont chargés en mode de préchargement (l'attribut des relliens correspondants est défini sur preload). Après cela, lorsqu'ils sont prêts à utiliser, appliquez leurs événements onloadpour les connecter à la page.

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="path/to/mystylesheet.css"></noscript>

Étant donné que tous les navigateurs ne prennent pas en charge la conception <a href="https://caniuse.com/#feat=link-rel-preload"><link rel="preload"></a>, le projet loadCSSoffre aux développeurs un polyfill pratique, qui est ajouté à la page après la description des liens pertinents:

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript>
    <link rel="stylesheet" href="path/to/mystylesheet.css">
</noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... }());
</script>

Trouble dans les priorités du réseau


Je n'ai jamais été un ardent fan de ce modèle. Le préchargement est un outil grossier. Les matériaux téléchargés à l'aide de liens d'attributs rel="preload"se battent avec succès avec d'autres matériaux pour les ressources réseau. L'utilisation preloadsuppose que les feuilles de style qui se chargent de manière asynchrone du fait qu'elles ne jouent pas un rôle critique dans la sortie d'une page reçoivent une très haute priorité des navigateurs.

L'image suivante, extraite de WebPageTest, illustre très bien ce problème. Aux lignes 3 à 6, vous pouvez voir le chargement asynchrone des fichiers CSS à l'aide d'un modèle preload. Mais, alors que les développeurs considèrent que ces fichiers ne sont pas si importants que leur téléchargement bloquerait le rendu, utilisezpreload signifie qu'ils seront chargés avant que le navigateur ne reçoive les ressources restantes.


Les fichiers CSS qui utilisent le modèle de préchargement lorsqu'ils sont chargés arriveront dans le navigateur plus tôt que les autres ressources, même si ce ne sont pas des ressources essentielles pour le rendu initial d'une page

Verrouillage de l'analyseur HTML


Les problèmes associés à la priorité de chargement des ressources sont déjà suffisants pour éviter d'utiliser le modèle dans la plupart des situations preload. Mais dans ce cas, la situation est aggravée par la présence d'une autre feuille de style, qui est chargée de la manière habituelle.

<link rel="stylesheet" href="path/to/main.css" />
<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">
<noscript>
    <link rel="stylesheet" href="path/to/mystylesheet.css">
</noscript>
<script>
/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... }());
</script>

Il y a les mêmes problèmes lors de l'utilisation preloadconduit au fait que les fichiers les plus importants ne sont pas prioritaires. Mais il est tout aussi important, et peut-être moins évident, quel effet cela a sur la capacité du navigateur à analyser la page.

Encore une fois, cela a déjà été écrit en détail , donc je recommande de lire ce matériel afin de mieux comprendre ce qui se passe. Ici, je vais en parler brièvement.

En règle générale, le chargement des styles bloque le rendu des pages. Le navigateur doit interroger et analyser les styles afin de pouvoir afficher la page. Cependant, cela n'empêche pas le navigateur d'analyser le reste du code HTML.

Les scripts, en revanche, bloquent l'analyseur s'ils ne sont pas marqués comme deferou async.

Étant donné que le navigateur doit supposer que le script peut manipuler le contenu de la page elle-même ou les styles qui lui sont appliqués, il doit faire attention au moment de l'exécution de ce script. Si le navigateur sait qu'un certain code CSS est en cours de chargement, il attendra l'arrivée de ce code CSS, puis exécutera le script. Et comme le navigateur ne peut pas continuer d'analyser le document tant que le script n'est pas exécuté, cela signifie que les styles ne bloquent plus uniquement le rendu. Ils empêchent le navigateur d'analyser le HTML.

Ce comportement est vrai pour les scripts externes et les scripts intégrés dans la page. Si le CSS se charge, les scripts en ligne ne s'exécutent pas jusqu'à ce que ce CSS arrive dans le navigateur.

Etude de problème


La façon la plus compréhensible de visualiser ce problème est d'utiliser les outils de développement Chrome (j'aime vraiment le niveau auquel ces outils ont grandi).

Parmi les outils Chrome, il y a un onglet Performanceavec lequel vous pouvez enregistrer le profil de chargement de la page. Je recommande de ralentir artificiellement la connexion réseau afin que le problème se manifeste plus clairement.

Dans ce cas, j'ai testé en utilisant la configuration réseau Fast 3G. Si vous regardez attentivement ce qui arrive au thread principal, vous pouvez comprendre que la demande de chargement du fichier CSS se produit au tout début de l'analyse HTML (environ 1,7 seconde après le début du chargement de la page).


Un petit rectangle sous le bloc d'analyse HTML représente une demande de fichier CSS.

Pendant la prochaine période, qui est d'environ une seconde, le thread principal est inactif. Ici, vous pouvez voir de petites îles d'activités. Il s'agit d'un déclenchement d'événements indiquant l'achèvement du chargement des styles; c'est l'envoi par le mécanisme de préchargement de ressources d'autres requêtes. Mais le navigateur arrête complètement l'analyse HTML.


Si vous regardez la situation dans son ensemble, il s'avère qu'après le début du chargement de CSS, le flux principal est inactif pendant plus de 1,1 seconde.

Ainsi, 2,8 secondes se sont écoulées, le style est chargé, le navigateur le traite. Ce n'est qu'alors que nous voyons le traitement du script intégré, puis le navigateur revient finalement à l'analyse HTML.


CSS arrive dans environ 2,8 secondes, après quoi nous voyons que le navigateur continue d'analyser HTML

Firefox est une belle exception


Le comportement ci-dessus est courant pour Chrome, Edge et Safari. Firefox est une belle exception Ă  la liste des navigateurs populaires.

Tous les autres navigateurs suspendent l'analyse HTML, mais utilisent un analyseur proactif (un moyen de préchargement des matériaux) pour afficher le code des liens vers les ressources externes et pour répondre aux demandes de chargement de ces ressources. Firefox, cependant, va plus loin dans ce domaine: il construit spéculativement une arborescence DOM, même s'il s'attend à ce que le script s'exécute.

À moins que le script ne manipule le DOM, ce qui entraîne la nécessité de rejeter les résultats de l'analyse spéculative, cette approche permet à Firefox d'en profiter. Bien sûr, si le navigateur doit supprimer l'arborescence DOM spéculativement construite, cela signifie qu'en construisant cette arborescence, cela n'a rien fait d'utile.

Il s'agit d'une approche intéressante. J'étais terriblement curieux de savoir à quel point c'est efficace. Maintenant, cependant, il n'y a aucune information à ce sujet dans Firefox Performance Profiler. Là, vous ne pouvez pas savoir si l'analyseur spéculatif a fonctionné, s'il est nécessaire de refaire le travail qu'il a effectué, et s'il doit encore être refait, comment cela affectera les performances.

J'ai parlé à ceux qui sont responsables des outils de développement de Firefox, et je peux dire qu'ils ont des idées intéressantes sur la façon de présenter ces informations dans le profileur à l'avenir. J'espère qu'ils réussiront.

Solution au problème


Dans le cas du client, que j'ai mentionné au tout début, la première étape pour résoudre ce problème semblait extrêmement simple: se débarrasser du modèle preload/polyfill. Le préchargement de CSS non critiques est inutile. Ici, vous devez passer à l'utilisation d' rel="preload"un attribut au lieu d' un media="print". C'est exactement ce que recommandent les experts du Groupe Filament. Cette approche vous permet en outre de vous débarrasser complètement du polyfill.

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

Cela nous place déjà dans une meilleure position: les priorités du réseau sont désormais bien mieux alignées sur l'importance réelle des téléchargements. Et nous nous débarrassons également du script intégré.

Dans ce cas, il existe encore un autre script intégré situé dans l'en-tête du document, sous la ligne qui initie la demande de chargement de CSS. Si vous déplacez ce script de sorte qu'il se trouve devant la ligne de chargement du CSS, cela éliminera le verrouillage de l'analyseur. Si vous analysez à nouveau la page à l'aide des outils de développement Chrome, la différence sera complètement évidente.


Avant d'apporter des modifications au code de la page, l'analyseur HTML s'est arrêté à la ligne 1939, après avoir rencontré un script intégré, et est resté ici pendant environ une seconde. Après l'optimisation, il a pu accéder à la ligne 5281

Auparavant, l'analyseur s'arrêtait à la ligne 1939 et attendait le chargement de CSS, mais maintenant il atteint la ligne 5281. Là, à la fin de la page, il y a un autre script intégré qui arrête à nouveau l'analyseur.

Il s'agit d'une solution rapide au problème. Ce n'est pas l'option qui représente la solution finale au problème. Changer l'ordre des éléments et se débarrasser du motifpreload/polyfilln'est que la première étape. Vous pouvez mieux résoudre ce problème en incorporant du code CSS critique dans une page, plutôt que de le charger à partir d'un fichier externe. Modèlepreload/polyfillConçu pour être utilisé en plus du CSS en ligne. Cela nous permet d'ignorer complètement les problèmes liés aux scripts et de nous assurer que le navigateur, après la première demande, dispose de tous les styles nécessaires au rendu de la page.

Mais pour l'instant, il convient de noter que nous pouvons obtenir une bonne amélioration des performances en apportant de très petites modifications au projet concernant la façon dont les styles sont chargés et l'ordre des éléments dans le DOM.

Sommaire


  • Si vous utilisez un loadCSSmodèle preload/polyfill, accĂ©dez au modèle de chargement de style print.
  • Si vous avez des styles externes qui sont chargĂ©s de la manière habituelle (c'est-Ă -dire en utilisant des liens rĂ©guliers vers des fichiers de ces styles), dĂ©placez tous les scripts intĂ©grĂ©s qui peuvent ĂŞtre dĂ©placĂ©s au-dessus des liens pour charger des styles.
  • IntĂ©grez des styles critiques dans la page afin d'assurer le dĂ©marrage le plus rapide possible du rendu.

Chers lecteurs! Avez-vous rencontré des problèmes pour ralentir le rendu des pages en raison de CSS?

PS
RUVDS félicite tous les professionnels de l'informatique le 8 mars!
Cette année, nous avons décidé de ne pas donner de tulipes et de ne pas faire de sélection de cadeaux geek. Nous avons pris un chemin différent et créé la page IT is female pour montrer la présence de femmes spécialistes en informatique.


All Articles