Añade atributos defer a todos los javascripts si es posible. Posponer la carga y ejecución de javascript permite al navegador comenzar el análisis de HTML, la representación y el pintado.
Así, cierto contenido estático provisional puede mostrarse muy pronto (o incluso antes) del proceso de arranque de Discourse. Esto debería ser suficiente para una velocidad de carga de página percibida por el usuario más rápida en la carga inicial de la página.
Eso haría que el LCP siguiera activo después de que EmberJS arranque y se vuelva a renderizar, sin abordar el problema principal con respecto a las nuevas clasificaciones de Google.
Ese es nuestro plan actual a medio plazo para abordar el LCP en Discourse.
¡A partir de Chrome 88, esto, por suerte, ya no es cierto!
Tampoco lo sabía hasta ahora. :))
“Antes de este cambio, la eliminación de un elemento hacía que dejara de considerarse un candidato válido para LCP. […] Después de este cambio, la eliminación de un elemento todavía se considera un candidato válido para LCP”.
“El cambio para incluir contenido que posteriormente se elimina del DOM como posibles pintados de contenido más grandes mejorará los tiempos de Largest Contentful Paint en sitios que tienen imágenes [para Discourse:elementos de texto] del mismo tamaño insertados varias veces. Este es un patrón común para los carruseles, así como para algunos frameworks de JavaScript que hacen renderizado del lado del servidor”.
0s-2s - pantalla en blanco:
WebPageTest ignora defer para JavaScript y descarga todos los JavaScript antes de realizar una primera pintura; esto funciona correctamente en un dispositivo real.
2.5s - LCP: contenido estático de la renderización del lado del servidor
3.5s - Cambio visual: logotipo cargado
6.5s - Cambio visual: contenido de la renderización de EmberJs
7s - Visual completo
PageSpeed Insights
Elemento Largest Contentful Paint
PageSpeed identifica correctamente el nodo de texto estático de la renderización del lado del servidor como el elemento FCP LCP: div.row > div.topic-body > div.post > p
Nodo de texto renderizado por EmberJs: div.row > div.topic-body > div.regular.contents > div.cooked > p
Pero parece que PageSpeed no utiliza el nodo de texto estático correctamente identificado para su resultado simulado: el FCP y LCP simulados son demasiado grandes.
Nota sobre el First Input Delay (Retraso de la primera entrada): Esperé hasta que la página se cargó completamente y luego hice clic en el fondo, es decir, después de que el renderizado de EmberJs terminara.
Nota sobre el First Input Delay (Retraso de la primera entrada): Aquí hice clic en el fondo inmediatamente cuando el contenido estático fue visible por primera vez. Añade mi tiempo de reacción encima de este FID.
Nota adicional sobre los percentiles debajo de las barras en estos gráficos:
Los percentiles no son muy relevantes ya que solo comparan los valores medidos con los valores de origen. El origen es una página web de TYPO3 con una instalación de Discourse en una subcarpeta.
Estoy totalmente de acuerdo en que Discourse es una aplicación web muy lenta y pesada en JS. Si podemos diferir los archivos CSS/JS, ayudará enormemente a acelerar LCP, FCP, FID, CLS.
Realmente ayudaría ver esto implementado, nosotros y muchas otras personas estamos enfrentando este problema. Todos los sitios de Discourse fallan en Core Web Vitals. Si servimos una página HTML estática rápida a los usuarios la primera vez y/o diferimos toda la lógica de JS/CSS en la primera carga inicial, ¡podemos acelerar todas las páginas y pasar las puntuaciones de CWV! Emocionado de ver esto implementado en una actualización principal de Discourse.
Todos los sitios de Discourse están perdiendo posiciones en Google debido a que los sitios no pasan Core Web Vitals.
Estamos abiertos a experimentar con esto en el núcleo. El “flash” de contenido con un estilo diferente puede ser un poco desconcertante, por lo que nos gustaría empezar con él detrás de una configuración del sitio “experimental” deshabilitada por defecto para empezar. De esa manera, los administradores del sitio pueden optar por habilitarlo si lo desean.
¿Puedes intentar agregar una configuración del sitio en tu PR @rrit? También sería bueno agregar algunas pruebas RSpec para verificar el comportamiento con la configuración habilitada / deshabilitada.
¿No significa eso que podemos simplemente poner un spinner a pantalla completa (que tiene 100% de ancho y 100% de alto) en la página renderizada por el servidor, y reemplazarlo por la aplicación Ember cuando finalmente arranca para obtener un LCP extremadamente bajo?
Podríamos hacer que este spinner sea un SVG que imite la interfaz de usuario de Discourse para que la transición sea más fluida y menos parecida a FOUC.
¿Solo se considerará la pintura de contenido más grande si realmente es la más grande (o al menos, del mismo tamaño) que lo que finalmente se renderiza?
¿Entonces usar la vista del rastreador funciona bastante bien porque el contenido (es decir, el texto) es en gran medida el mismo?
(Estoy adivinando aquí, basándome en las capturas de pantalla anteriores; no he probado un spinner a pantalla completa)
Tuve que deshabilitar el defer tag para QUnit Test Runner: app/views/qunit/index.html.erb
Antes, las pruebas QUnit todavía se ejecutaban con la bandera de funcionalidad "javascript defer" = false. Y ahora las pruebas también se ejecutan con "javascript defer" = true.
Las imágenes de pantalla completa, que son visualmente equivalentes a las imágenes de fondo, ya no se consideran el mayor elemento de pintura con contenido (largest contentful paint).
Para los elementos de texto, solo se considera el tamaño de sus nodos de texto (el rectángulo más pequeño que abarca todos los nodos de texto).
Para todos los elementos, no se consideran los márgenes, rellenos o bordes aplicados a través de CSS.
Es por eso que el nodo de texto estático debe renderizarse exactamente del mismo tamaño que el nodo de texto de EmberJs.
O incluso ligeramente más grande aumentando el line-height.
Por ejemplo, si el ancho de los nodos de texto no coincide, hay muchos casos geométricos introducidos por diferentes saltos de línea en los que el nodo de texto estático se vuelve más pequeño que el de EmberJs.
En realidad, utilicé la representación noscript de las publicaciones dentro de la página de un tema. Las clases CSS coinciden ligeramente con las reales, por lo que el aspecto es el mismo.
En el POC hay dos características combinadas, ¿las separamos en dos indicadores de características experimentales?
JavaScript con etiqueta defer (indicador de características en el panel de configuración) (indicador de características oculto ya que se necesita una reconstrucción del contenedor o un vaciado de la caché del tema) ← Arreglo: cambio en caliente con caché
Mostrar contenido estático en la vista del tema (indicador de características en el panel de configuración)
Por supuesto, el impacto total en LCP solo se logra utilizando ambos: FCP: contenido estático
Puede haber instancias de Discourse donde los plugins o componentes temáticos fallen al diferir el JS. Al separar estas características, pueden obtener una pequeña ganancia en el contenido estático sin diferir el JS: FCP: contenido estático sin diferir JS
Esperemos otros 7-14 días para ver si hay más mejoras en las páginas móviles, ya que los valores se promedian durante los últimos 28 días, y actualmente solo han transcurrido 12 días con el POC aplicado.
La Prueba de Concepto (POC) se aplica desde el 30/01/2022 y tardó más de 4 semanas en afectar a todas las páginas en el informe “Core Web Vitals” de Google Search Console, basado en datos de CrUX.
Todas las páginas de temas están en la zona verde de LCP (medido por CrUX):
Escritorio: LCP 1.7 seg
Móvil: LCP 2.0 seg
Datos de LCP: Google Search Console/CrUX
Impresión de Google Search Console con la POC aplicada desde el 30/01/2022:
@rrit ¡Gracias por compartir los datos de tu sitio! Hemos estado discutiendo esto internamente y me temo que no agregaremos esta funcionalidad al núcleo de Discourse por el momento.
Si bien las métricas de Web Vital que compartiste son muy impresionantes, el destello de contenido de ‘vista de rastreador’ no crea una buena experiencia de usuario. Los cambios de estilo que has realizado ciertamente ayudan, pero deberán ajustarse para cada sitio de Discourse que tenga estilo personalizado.
Nuestro objetivo a largo plazo es implementar la renderización real del lado del servidor utilizando algo como Ember FastBoot. Teóricamente, eso proporcionaría las mismas mejoras estadísticas que has medido, al tiempo que ofrecería una experiencia de usuario fluida. Preferiríamos centrar nuestros esfuerzos en ese objetivo.
Dicho todo esto, Discourse es súper extensible, así que creo que debería ser totalmente posible implementar tu idea en un plugin de Discourse y luego compartirlo aquí en Plugin.
El mayor cambio que has hecho en el PR principal es agregar el atributo defer a las etiquetas de script. Anular todos esos lugares desde un plugin sería muy difícil. Sin embargo, creo que el mismo resultado podría lograrse con un enfoque basado en middleware. Encontré esta publicación de blog que describe un problema similar:
Usando esa técnica, podrías escribir un middleware que verifique las respuestas text/html, las analice y luego agregue atributos defer donde sea necesario.
Agregar middleware desde un plugin se puede hacer algo como esto:
# name: my-plugin
# about: Mi descripción del 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 encuentras algún obstáculo con un enfoque basado en plugins, no dudes en publicar aquí y estaremos encantados de intentar indicarte la dirección correcta.