Índice
- ¿Por qué es necesaria la mejora de la velocidad en nuestros esfuerzos de SEO?
- React Hydration: por qué hay un JSON en HTML
- ¿De qué páginas estamos hablando exactamente?
- Ahora, una mirada a la arquitectura
- Cambio de arquitectura
- Ejemplo de flujo de datos
- Cómo medir el impacto del cambio
- Conclusiones
- Impacto en el rendimiento
- Solución en capas
Este artículo muestra un estudio de caso sobre el rendimiento de la página de destino de Bookaway. Veremos cómo cuidar los accesorios que enviamos a las páginas Next.js puede mejorar los tiempos de carga y Web Vitals.
Sé lo que estás pensando. Aquí hay otro artículo sobre cómo reducir las dependencias de JavaScript y el tamaño del paquete enviado al cliente. Pero este es un poco diferente, lo prometo.
Este artículo trata sobre un par de cosas que enfrentó Bookaway y nosotros (como empresa en la industria de viajes) logramos optimizar nuestras páginas para que el HTML que enviamos sea más pequeño. Un HTML más pequeño significa menos tiempo para que Google descargue y procese esas largas cadenas de texto.
Por lo general, el tamaño del código HTML no es un gran problema, especialmente para páginas pequeñas, que no requieren muchos datos o páginas que no están orientadas a SEO. Sin embargo, en nuestras páginas, el caso fue diferente, ya que nuestra base de datos almacena una gran cantidad de datos y necesitamos ofrecer miles de páginas de destino a escala.
Quizás se pregunte por qué necesitamos una escala así. Bueno, Bookaway trabaja con 1500 operadores y brinda más de 20 mil servicios en 63 países con un crecimiento del 200% año tras año (antes de Covid-19). En 2019 vendimos 500.000 entradas al año, por lo que nuestras operaciones son complejas y necesitamos mostrarlo con nuestras páginas de destino de una manera atractiva y rápida. Tanto para bots de Google (SEO) como para clientes reales.
En este artículo, te explicaré:
- cómo descubrimos que el tamaño del HTML es demasiado grande;
- cómo se redujo;
- los beneficios de este proceso (es decir, crear una arquitectura mejorada, mejorar la organización de las odas, proporcionar un trabajo sencillo para que Google indexe decenas de miles de páginas de destino y entregar muchos menos bytes al cliente, especialmente adecuado para personas con conexiones lentas).
Pero primero, hablemos de la importancia de mejorar la velocidad.
¿Por qué es necesaria la mejora de la velocidad en nuestros esfuerzos de SEO?
Conozca " Web Vitals ", pero en particular, conozca LCP (Largest Contentful Paint):
“La pintura con contenido más grande (LCP) es una métrica importante y centrada en el usuario para medir la velocidad de carga percibida porque marca el punto en la línea de tiempo de carga de la página en el que es probable que se haya cargado el contenido principal de la página; un LCP rápido ayuda a asegurar al usuario que la página está útil ."
El objetivo principal es tener un LCP lo más pequeño posible. Parte de tener un LCP pequeño es permitir que el usuario descargue HTML tan pequeño como sea posible. De esa manera, el usuario puede comenzar el proceso de pintar el contenido más grande lo antes posible.
Si bien LCP es una métrica centrada en el usuario, reducirla debería ser de gran ayuda para los robots de Google, como afirma Googe:
“La Web es un espacio casi infinito que excede la capacidad de Google para explorar e indexar cada URL disponible. Como resultado, existen límites en cuanto al tiempo que el robot de Google puede dedicar a rastrear un solo sitio. La cantidad de tiempo y recursos que Google dedica a rastrear un sitio se denomina comúnmente presupuesto de rastreo del sitio”.
— “ SEO avanzado ”, Documentación central de búsqueda de Google
Una de las mejores formas técnicas de mejorar el presupuesto de rastreo es ayudar a Google a hacer más en menos tiempo :
P : “¿La velocidad del sitio afecta mi presupuesto de rastreo? ¿Qué tal los errores?
R : “Hacer que un sitio sea más rápido mejora la experiencia de los usuarios y al mismo tiempo aumenta la velocidad de rastreo. Para Googlebot, un sitio rápido es una señal de que los servidores están en buen estado para que pueda obtener más contenido a través de la misma cantidad de conexiones”.
En resumen, los robots de Google y los clientes de Bookaway tienen el mismo objetivo: ambos quieren que el contenido se entregue rápidamente. Dado que nuestra base de datos contiene una gran cantidad de datos para cada página, debemos agregarlos de manera eficiente y enviar algo pequeño y delgado a los clientes.
Las investigaciones sobre formas en que podemos mejorar nos llevaron a descubrir que hay un JSON grande incrustado en nuestro HTML, lo que hace que el HTML sea grueso. Para ese caso, necesitaremos comprender React Hydration.
React Hydration: por qué hay un JSON en HTML
Esto sucede debido a cómo funciona la renderización del lado del servidor en React y Next.js:
- Cuando la solicitud llega al servidor, debe crear un HTML basado en una recopilación de datos. Esa colección de datos es el objeto devuelto por
getServerSideProps
. - Reaccionó obtuvo los datos. Ahora entra en juego en el servidor. Se construye en HTML y lo envía.
- Cuando el cliente recibe el HTML, inmediatamente se muestra dolorido frente a él. Mientras tanto, se descarga y ejecuta React javascript.
- Cuando finaliza la ejecución de JavaScript, React entra en juego nuevamente, ahora en el cliente. Genera el HTML nuevamente y adjunta detectores de eventos. Esta acción se llama hidratación .
- Como React construye nuevamente el HTML para el proceso de hidratación, requiere la misma recopilación de datos utilizada en el servidor (consulte nuevamente
1.
). - Esta recopilación de datos está disponible insertando el JSON dentro de una etiqueta de script con id
__NEXT_DATA__
.
¿De qué páginas estamos hablando exactamente?
Como necesitamos promocionar nuestras ofertas en los motores de búsqueda, ha surgido la necesidad de páginas de destino. La gente normalmente no busca el nombre de una línea de autobús específica, sino más bien, "¿Cómo llegar de Bangkok a Pattaya?". Hasta ahora, hemos creado cuatro tipos de páginas de destino que deberían responder a este tipo de consultas:
- Ciudad A a Ciudad B
Todas las líneas se extendían desde una estación en la Ciudad A hasta una estación en la Ciudad B (por ejemplo, de Bangkok a Pattaya ). - Ciudad
Todas las líneas que pasan por una ciudad específica. (por ejemplo, Cancún ) - País
Todas las líneas que pasan por un país específico. (por ejemplo, Italia ) - Estación
Todas las líneas que pasan por una estación específica. (por ejemplo, Hanoi-aeropuerto )
Ahora, una mirada a la arquitectura
Echemos un vistazo de alto nivel y muy simplificado a la infraestructura que impulsa las páginas de destino de las que estamos hablando. Las partes interesantes se encuentran en 4
y 5
. Ahí es donde se desperdician las partes: Blog sobre Ajedrez
Conclusiones clave del proceso
- La solicitud está afectando a la
getInitialProps
función. Esta función se ejecuta en el servidor. La responsabilidad de esta función es recuperar los datos necesarios para la construcción de una página. - Los datos sin procesar devueltos por los servidores REST se pasan tal cual a React.
- Primero, se ejecuta en el servidor. Dado que los datos no agregados se transfirieron a React, React también es responsable de agregar los datos en algo que puedan usar los componentes de la interfaz de usuario (más sobre esto en las siguientes secciones).
- El HTML se envía al cliente, junto con los datos sin procesar. Entonces React vuelve a entrar en juego también en el cliente y hace el mismo trabajo. Porque se necesita hidratación (más sobre eso en las siguientes secciones). Entonces React está haciendo el trabajo de agregación de datos dos veces.
El problema
El análisis del proceso de creación de nuestra página nos llevó al hallazgo de Big JSON incrustado dentro del HTML. Es difícil decir exactamente qué tamaño tiene. Cada página es ligeramente diferente porque cada estación o ciudad tiene que agregar un conjunto de datos diferente. Sin embargo, es seguro decir que el tamaño JSON podría llegar a 250 kb en páginas populares. Posteriormente se redujo a tamaños de entre 5 y 15 kb. Reducción considerable. En algunas páginas, rondaba los 200-300 kb. Eso es grande .
El JSON grande está incrustado dentro de una etiqueta de script con una identificación de ___NEXT_DATA___
:
script type="application/json"// Huge JSON here./script
Si desea copiar fácilmente este JSON en su portapapeles, pruebe este fragmento en su página Next.js:
copy($('#__NEXT_DATA__').innerHTML)
Surge una pregunta.
¿Porque es tan grande? ¿Que hay ahi?
Una gran herramienta, el analizador de tamaño JSON , sabe cómo procesar un JSON y muestra dónde reside la mayor parte del tamaño.
Estos fueron nuestros hallazgos iniciales al examinar la página de una estación :
Hay dos problemas con el análisis:
- Los datos no están agregados.
Nuestro HTML contiene la lista completa de productos granulares. No los necesitamos para pintar en pantalla. Los necesitamos para métodos de agregación. Por ejemplo, estamos obteniendo una lista de todas las líneas que pasan por esta estación. Cada línea tiene un proveedor. Pero necesitamos reducir la lista de líneas a una matriz de 2 proveedores. Eso es todo. Veremos un ejemplo más adelante. - Campos innecesarios.
Al profundizar en cada objeto, vimos algunos campos que no necesitamos en absoluto. No para fines de agregación ni para métodos de pintura. Esto se debe a que recuperamos los datos de la API REST. No podemos controlar qué datos recuperamos.
Esos dos problemas demostraron que las páginas necesitan un cambio de arquitectura. Pero espera. ¿Por qué necesitamos un JSON de datos incrustado en nuestro HTML en primer lugar?
Cambio de arquitectura
El problema del JSON muy grande tenía que resolverse con una solución ordenada y en capas. ¿Cómo? Pues añadiendo las capas marcadas en verde en el siguiente diagrama:
Algunas cosas a tener en cuenta:
- La doble agregación de datos se eliminó y se consolidó para que solo se realice una vez en el servidor Next.js;
- Se agregó la capa Graphql Server. Eso asegura que obtengamos solo los campos que queremos. La base de datos puede crecer con muchos más campos para cada entidad, pero eso ya no nos afectará;
PageLogic
función agregada engetServerSideProps
. Esta función obtiene datos no agregados de los servicios de back-end. Esta función agrega y prepara los datos para los componentes de la interfaz de usuario. (Se ejecuta sólo en el servidor).
Ejemplo de flujo de datos
Queremos renderizar esta sección desde una página de estación :
Necesitamos saber quiénes son los proveedores que operan en una determinada estación. Necesitamos recuperar todas las líneas para el lines
punto final REST. Esa es la respuesta que obtuvimos (el propósito de ejemplo, en realidad, era mucho más amplio):
[ { id: "58a8bd82b4869b00063b22d2", class: "Standard", supplier: "Hyatt-Mosciski", type: "bus", }, { id: "58f5e40da02e97f000888e07a", class: "Luxury", supplier: "Hyatt-Mosciski", type: "bus", }, { id: "58f5e4a0a02e97f000325e3a", class: 'Luxury', supplier: "Jones Ltd", type: "minivan", },];[ { supplier: "Hyatt-Mosciski", amountOfLines: 2, types: ["bus"] }, { supplier: "Jones Ltd", amountOfLines: 1, types: ["minivan"] },];
Como puede ver, tenemos algunos campos irrelevantes. pictures
y id
no van a desempeñar ningún papel en la sección. Entonces llamaremos al servidor Graphql y solicitaremos solo los campos que necesitamos. Entonces ahora se ve así:
[ { supplier: "Hyatt-Mosciski", type: "bus", }, { supplier: "Hyatt-Mosciski", type: "bus", }, { supplier: "Jones Ltd", type: "minivan", },];
Ese es un objeto más fácil con el que trabajar. Es más pequeño, más fácil de depurar y requiere menos memoria en el servidor. Pero aún no está agregado. Esta no es la estructura de datos requerida para la representación real.
Enviémoslo a la PageLogic
función para procesarlo y ver qué obtenemos:
[ { supplier: "Hyatt-Mosciski", amountOfLines: 2, types: ["bus"] }, { supplier: "Jones Ltd", amountOfLines: 1, types: ["minivan"] },];
Esta pequeña recopilación de datos se envía a la página Next.js.
Ahora está listo para la representación de la interfaz de usuario. No se necesitan más crujidos ni preparativos. Además, ahora es muy compacto en comparación con la recopilación de datos inicial que extrajimos. Esto es importante porque de esa manera enviaremos muy pocos datos al cliente.
Cómo medir el impacto del cambio
Reducir el tamaño de HTML significa que hay menos bits para descargar. Cuando un usuario solicita una página, obtiene HTML completo en menos tiempo. Esto se puede medir en content download
el recurso HTML en el panel de red .
Conclusiones
Ofrecer recursos reducidos es esencial, especialmente cuando se trata de HTML. Si HTML se está volviendo popular, no nos queda espacio para recursos CSS o JavaScript en nuestro presupuesto de rendimiento .
Es una buena práctica asumir que muchos usuarios del mundo real no usarán un iPhone 12, sino un dispositivo de nivel medio en una red de nivel medio. Resulta que los niveles de rendimiento son bastante ajustados, como sugiere el artículo de gran prestigio :
“Gracias al progreso en las redes y los navegadores (pero no en los dispositivos), ha surgido un límite presupuestario global más generoso para los sitios construidos de manera "moderna". Ahora podemos permitirnos ~100 KB de HTML/CSS/fuentes y ~300-350 KB de JS (en formato gzip). Este límite empírico debería mantenerse durante al menos uno o dos años. Como siempre, el diablo está en las notas a pie de página, pero la línea principal no cambia: cuando construimos el mundo digital hasta los límites de los mejores dispositivos, construimos uno menos utilizable para más del 80% de los usuarios del mundo”.
Impacto en el rendimiento
Medimos el impacto en el rendimiento según el tiempo que lleva descargar el HTML con una aceleración lenta de 3g. esa métrica se llama "descarga de contenido" en Chrome Dev Tools .
A continuación se muestra un ejemplo de métrica para una página de estación :
Tamaño HTML (antes de gzip) | Tiempo de descarga HTML (3G lento) | |
---|---|---|
Antes | 370kb | 820ms |
Después | 166 | 540ms |
cambio total | Disminución de 204kb | 34% Disminución |
Solución en capas
Los cambios de arquitectura incluyeron capas adicionales:
- Servidor GraphQl : ayuda a buscar exactamente lo que queremos.
- Función dedicada para agregación : se ejecuta solo en el servidor.
Los cambios, además de puras mejoras de rendimiento, también ofrecieron una organización del código y una experiencia de depuración mucho mejores:
- Toda la lógica de reducción y agregación de datos ahora centralizada en una única función;
- Las funciones de la interfaz de usuario ahora son mucho más sencillas. Sin agregación, sin procesamiento de datos. Simplemente obtienen datos y los pintan;
- Depurar el código del servidor es más agradable ya que extraemos solo los datos que necesitamos: no más campos innecesarios provenientes de un punto final REST.
(vf, il)Explora más en
- Siguiente.js
- Actuación
- javascript
- Estudios de caso
Tal vez te puede interesar:
- ¿Deberían abrirse los enlaces en ventanas nuevas?
- 24 excelentes tutoriales de AJAX
- 70 técnicas nuevas y útiles de AJAX y JavaScript
- Más de 45 excelentes recursos y repositorios de fragmentos de código
Reducción de la carga útil HTML con Next.js (estudio de caso)
¿Por qué es necesaria la mejora de la velocidad en nuestros esfuerzos de SEO?React Hydration: por qué hay un JSON en HTML¿De qué páginas estamos hablando
programar
es
https://aprendeprogramando.es/static/images/programar-reduccion-de-la-carga-util-html-con-next-1095-0.jpg
2024-12-03
Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente