Qu’en est-il de : Reporter les scripts javascript de Discourse
Ajoutez des attributs defer à tous les scripts javascript si possible. Reporter le chargement et l’exécution des scripts javascript permet au navigateur de commencer l’analyse HTML, le rendu et la peinture.
Ainsi, un contenu statique temporaire peut être affiché très tôt dans le processus de démarrage de Discourse (ou même avant). Cela devrait suffire pour une vitesse de chargement de page perçue par l’utilisateur plus rapide lors du premier chargement.
Les idées sur la façon de résoudre ce problème sont les bienvenues.
Chargement javascript : async vs defer vs none
En savoir plus sur les options de chargement javascript - y compris defer : Efficiently load JavaScript with defer and async
(Il ne s’agit pas d’accélérer le véritable démarrage de Discourse.)
Fastboot/réhydratation
J’ai lu cet article :
La conclusion semble être une implémentation de Fastboot/réhydratation.
Y a-t-il un calendrier pour cela ?
Cela provoquerait le LCP toujours après le démarrage et le ré-rendu d’EmberJS, sans résoudre le problème principal concernant les nouveaux classements Google.
C’est notre plan actuel à moyen terme pour résoudre le LCP dans Discourse.
Depuis Chrome 88, ce n’est heureusement plus le cas !
Je ne le savais pas non plus jusqu’à maintenant. :))
« Avant ce changement, un élément supprimé n’était plus considéré comme un candidat LCP valide. […] Après ce changement, un élément supprimé est toujours considéré comme un candidat LCP valide. »
« Le changement consistant à inclure le contenu qui est ensuite supprimé du DOM comme potentiels plus grands éléments de contenu pour le rendu améliorera les temps de Largest Contentful Paint sur les sites qui ont des images [pour Discourse :des éléments de texte] de la même taille insérés plusieurs fois. C’est un schéma courant pour les carrousels, ainsi que pour certains frameworks JavaScript qui font du rendu côté serveur (server-side rendering). »
Journal des modifications LCP
Il pourrait y avoir d’autres bons changements à l’avenir :
0s-2s - écran vierge :
WebPageTest ignore defer pour JavaScript et télécharge tous les scripts avant d’effectuer une première peinture - cela fonctionne correctement sur un appareil réel.
2,5s - LCP : contenu statique du rendu côté serveur
3,5s - Changement visuel : logo chargé
6,5s - Changement visuel : contenu rendu par EmberJs
7s - Visuel complet
PageSpeed Insights
Élément Largest Contentful Paint
PageSpeed identifie correctement le nœud de texte statique du rendu côté serveur comme élément FCP LCP : div.row > div.topic-body > div.post > p
Nœud de texte rendu par EmberJs : div.row > div.topic-body > div.regular.contents > div.cooked > p
Mais il semble que PageSpeed n’utilise pas le nœud de texte statique correctement identifié pour son résultat simulé : le FCP et le LCP simulés sont trop importants.
Attendons encore 14 à 28 jours pour obtenir des données « réelles » du Chrome UX Report avec le POC implémenté.
Statistiques sans le POC implémenté pour la page de sujet testée :
(Les données concernent cette URL de sujet unique – et non l’ensemble de l’origine.)
Remarque sur le délai de première entrée (First Input Delay) : J’ai attendu que la page soit complètement chargée, puis j’ai cliqué sur l’arrière-plan - donc après la fin du rendu EmberJs.
Remarque sur le délai de première entrée (First Input Delay) : Ici, j’ai cliqué sur l’arrière-plan immédiatement lorsque le contenu statique était visible pour la première fois. Ajoutez mon temps de réaction en plus de ce FID.
Note supplémentaire sur les percentiles sous les barres de ces graphiques :
Les percentiles ne sont pas très pertinents car ils ne comparent que les valeurs mesurées aux valeurs d’origine. L’origine est une page web TYPO3 avec une installation de Discourse dans un sous-dossier.
Je suis tout à fait d’accord, Discourse est une application web très lente et gourmande en JS. Si nous pouvons différer les fichiers CSS/JS, cela aidera énormément à accélérer LCP, FCP, FID, CLS.
Ce serait vraiment utile de voir cela se concrétiser. Nous et beaucoup d’autres personnes rencontrons ce problème. Tous les sites Discourse échouent aux Core Web Vitals. Si nous servons une page HTML STATIQUE rapide aux utilisateurs lors du premier chargement et/ou si nous différons toute la logique JS/CSS lors du premier chargement initial, nous pourrons ainsi accélérer toutes les pages et passer les scores CWV ! J’ai hâte de voir cela en direct dans une mise à jour majeure de Discourse.
Tous les sites Discourse voient leur classement Google décliner car ils ne passent pas les Core Web Vitals.
Nous sommes ouverts à l’expérimentation de cela dans le cœur. Le « flash » de contenu de styles différents peut être un peu déconcertant, nous aimerions donc commencer avec cela désactivé par défaut derrière un paramètre de site « expérimental ». De cette façon, les administrateurs du site peuvent choisir de l’activer s’ils le souhaitent.
Êtes-vous en mesure d’essayer d’ajouter un paramètre de site dans votre PR @rrit ? Il serait également bon d’ajouter des tests RSpec pour vérifier le comportement avec le paramètre activé / désactivé.
Cela ne signifie-t-il pas que nous pouvons simplement placer un spinner plein écran (qui a 100% de largeur et 100% de hauteur) sur la page rendue par le serveur, et le remplacer par l’application Ember lorsqu’elle démarre enfin pour obtenir un LCP extrêmement bas ?
Nous pourrions faire de ce spinner un SVG qui imite l’interface utilisateur de Discourse afin que la transition soit plus fluide et moins de type FOUC.
Il ne sera considéré comme la plus grande peinture de contenu que s’il est réellement le plus grand (ou au moins de la même taille) que ce qui est finalement rendu ?
Donc, l’utilisation de la vue crawler fonctionne assez bien car le contenu (c’est-à-dire le texte) est en grande partie le même ?
(Je spécule surtout ici, d’après les captures d’écran ci-dessus - je n’ai pas essayé de spinner plein écran)
J’ai dû désactiver le defer tag pour le QUnit Test Runner : app/views/qunit/index.html.erb
Avant, les tests QUnit s’exécutaient toujours avec le Feature flag "javascript defer" = false. Et maintenant, les tests s’exécutent aussi avec "javascript defer" = true.
Les images plein écran, qui sont visuellement équivalentes aux images d’arrière-plan, ne sont plus considérées comme le plus grand élément d’affichage de contenu (largest contentful paint).
Pour les éléments de texte, seule la taille de leurs nœuds de texte est prise en compte (le plus petit rectangle qui englobe tous les nœuds de texte).
Pour tous les éléments, les marges, le rembourrage ou les bordures appliqués via CSS ne sont pas pris en compte.
C’est pourquoi le nœud de texte statique doit être rendu exactement de la même taille que le nœud de texte EmberJs.
Ou même légèrement plus grand en augmentant la line-height.
Par exemple, si la largeur des nœuds de texte ne correspond pas, il existe de nombreux cas géométriques introduits par différents sauts de ligne où le nœud de texte statique devient plus petit que celui d’EmberJs.
J’ai en fait utilisé le rendu noscript des publications à l’intérieur d’une page de sujet. Les classes CSS correspondent légèrement aux vraies - donc l’apparence est égale.
Dans le POC, deux fonctionnalités sont combinées - devons-nous les diviser en deux drapeaux de fonctionnalités expérimentales ?
JavaScript avec balise defer (drapeau de fonctionnalité dans le tableau de bord des paramètres) (drapeau de fonctionnalité caché car une reconstruction du conteneur ou une purge du cache du thème est nécessaire pour cela) ← Correction : commutation à chaud avec cache
Affichage de contenu statique dans la vue du sujet (drapeau de fonctionnalité dans le tableau de bord des paramètres)
Voici les drapeaux de fonctionnalités : feature flags
Bien sûr, l’impact complet sur le LCP n’est obtenu qu’en utilisant les deux : FCP : contenu statique
Il pourrait y avoir des instances de Discourse où les plugins ou les composants de thème échouent lors de la mise en attente du JS. En divisant ces fonctionnalités, elles peuvent obtenir un petit gain sur le contenu statique sans mettre en attente le JS : FCP : contenu statique sans mise en attente du JS
Attendons encore 7 à 14 jours pour voir, espérons-le, davantage d’améliorations pour les pages mobiles, car les valeurs sont moyennées sur les 28 derniers jours - seulement 12 jours comptent avec le POC appliqué actuellement.
Le PoC est appliqué depuis le 30/01/2022 et il a fallu plus de 4 semaines pour affecter toutes les pages dans le rapport « Core Web Vitals » de la Google Search Console - basé sur les données CrUX.
Toutes les pages de sujets sont dans la zone verte LCP (mesurée par CrUX) :
Bureau : LCP 1,7 s
Mobile : LCP 2,0 s
Données LCP : Google Search Console/CrUX
Impression de la Google Search Console avec le PoC appliqué depuis le 30/01/2022 :
@rrit merci de partager les données de votre site ! Nous en avons discuté en interne et je crains que nous n’ajoutions pas cette fonctionnalité au cœur de Discourse pour le moment.
Bien que les métriques Web Vital que vous avez partagées soient très impressionnantes, le flash de contenu de « vue crawler » n’offre pas une bonne expérience utilisateur. Les modifications de style que vous avez apportées aident certainement, mais elles devront être ajustées pour chaque site Discourse ayant un style personnalisé.
Notre objectif à long terme est de mettre en œuvre un véritable rendu côté serveur à l’aide de quelque chose comme Ember FastBoot. Théoriquement, cela fournirait les mêmes améliorations statistiques que celles que vous avez mesurées, tout en offrant une expérience utilisateur transparente. Nous préférerions concentrer nos efforts sur cet objectif.
Cela dit, Discourse est super extensible, donc je pense qu’il devrait être tout à fait possible de mettre en œuvre votre idée dans un plugin Discourse et de le partager ici dans Plugin.
Le plus grand changement que vous avez apporté dans le PR principal est d’ajouter l’attribut defer aux balises script. Remplacer tous ces emplacements à partir d’un plugin serait très difficile. Cependant, je pense que le même résultat pourrait être obtenu avec une approche basée sur des middlewares. J’ai trouvé cet article de blog qui décrit un problème similaire :
En utilisant cette technique, vous pourriez écrire un middleware qui vérifie les réponses text/html, les analyse, puis ajoute des attributs defer si nécessaire.
L’ajout de middlewares à partir d’un plugin peut se faire comme ceci :
# name: my-plugin
# about: Ma description de plugin
# version: 1.0
# url: https://example.org
require_relative "lib/script_defer_middleware"
on(:after_initializers) do
Rails.configuration.middleware.use(ScriptDeferMiddleware)
end
Si vous rencontrez des obstacles avec une approche basée sur des plugins, n’hésitez pas à poster ici et nous serons heureux d’essayer de vous orienter dans la bonne direction.