Optimiza la carga de secuencias de comandos de terceros en Next.js

Comprender la visión detrás del componente de secuencia de comandos de Next.js, que proporciona una solución integrada para optimizar la carga de secuencias de comandos de terceros

Elena Sohoni
Leena Sohoni

Alrededor del 45% de las solicitudes de sitios web publicados en dispositivos móviles y computadoras de escritorio son solicitudes de terceros, de las cuales el 33% son secuencias de comandos. El tamaño, la latencia y la carga de las secuencias de comandos de terceros pueden afectar significativamente el rendimiento de un sitio. El componente de secuencia de comandos de Next.js incluye prácticas recomendadas incorporadas y configuraciones predeterminadas para ayudar a los desarrolladores a incorporar secuencias de comandos de terceros en sus aplicaciones y, al mismo tiempo, abordar posibles problemas de rendimiento desde el primer momento.

Secuencias de comandos de terceros y su impacto en el rendimiento

Las secuencias de comandos de terceros permiten que los desarrolladores web aprovechen las soluciones existentes para implementar funciones comunes y reducir el tiempo de desarrollo. Sin embargo, los creadores de estos guiones, por lo general, no tienen ningún incentivo para considerar el impacto en el rendimiento del sitio web que los usuarios los consumen. Estas secuencias de comandos también son una caja negra para los desarrolladores que las usan.

Las secuencias de comandos representan una cantidad significativa de bytes de terceros descargados por sitios web en diferentes categorías de solicitudes de terceros. De forma predeterminada, el navegador prioriza las secuencias de comandos según el lugar en el que se encuentren en el documento, lo que puede retrasar el descubrimiento o la ejecución de secuencias de comandos críticas para la experiencia del usuario.

Las bibliotecas de terceros necesarias para el diseño deben cargarse antes de que se procese la página. Los terceros que no se necesiten para la renderización inicial deben diferirse a fin de que no bloqueen otros procesos en el subproceso principal. Lighthouse tiene dos auditorías para marcar las secuencias de comandos que bloquean la renderización o las secuencias de comandos que bloquean la renderización principal.

Realiza auditorías de Lighthouse para eliminar los recursos que bloquean la renderización y minimizar el uso de terceros.

Es importante tener en cuenta la secuencia de carga de recursos de tu página para que los recursos críticos no se retrasen y los recursos no críticos no bloqueen los críticos.

Si bien existen prácticas recomendadas para reducir el impacto de los terceros, es posible que no todos sepan cómo implementarlas para cada tercero que utilicen. Esto puede ser complicado por los siguientes motivos:

  • En promedio, los sitios web utilizan entre 21 y 23 terceros diferentes, incluidas las secuencias de comandos, en los dispositivos móviles y las computadoras de escritorio. El uso y las recomendaciones pueden variar para cada uno.
  • La implementación de varios terceros puede diferir en función de si se usa un framework o una biblioteca de IU en particular.
  • Las bibliotecas de terceros más nuevas se presentan con frecuencia.
  • Los diversos requisitos comerciales relacionados con el mismo tercero dificultan que los desarrolladores estandaricen su uso.

Aurora se enfoca en secuencias de comandos de terceros

Parte de la colaboración de Aurora con herramientas y frameworks web de código abierto consiste en proporcionar valores predeterminados sólidos y herramientas bien definidas para ayudar a los desarrolladores a mejorar aspectos de la experiencia del usuario, como el rendimiento, la accesibilidad, la seguridad y la preparación para dispositivos móviles. En 2021, nos enfocamos en ayudar a las pilas de framework a mejorar la experiencia del usuario y sus métricas de Métricas web esenciales.

Uno de los pasos más importantes para lograr nuestro objetivo de mejorar el rendimiento del framework fue investigar la secuencia de carga ideal de secuencias de comandos de terceros en Next.js. Los frameworks como Next.js tienen una posición única para proporcionar funciones predeterminadas y funciones útiles que ayudan a los desarrolladores a cargar con eficiencia los recursos, incluidos los terceros. Analizamos una gran cantidad de datos de HTTP Archive y Lighthouse para descubrir qué terceros se renderizan bloques más en diferentes frameworks.

Para solucionar el problema de que el subproceso principal bloquea secuencias de comandos de terceros utilizadas en una aplicación, creamos el componente de secuencia de comandos. El componente encapsula funciones de secuenciación a fin de proporcionar a los desarrolladores mejores controles para la carga de secuencias de comandos de terceros.

Secuencia de secuencias de comandos de terceros sin un componente de framework

La guía disponible para reducir el impacto de las secuencias de comandos que bloquean el procesamiento proporcionan los siguientes métodos para cargar y secuenciar de manera eficiente secuencias de comandos de terceros:

  1. Usa los atributos async o defer con las etiquetas <script> que le indiquen al navegador que cargue secuencias de comandos no críticas de terceros sin bloquear el analizador de documentos. Las secuencias de comandos que no se requieren para la carga inicial de la página o la primera interacción del usuario pueden considerarse no críticas.

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Establece conexiones anticipadas a los orígenes necesarios con preconnect y dns-prefetch. Esto permite que las secuencias de comandos importantes comiencen a descargarse antes.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Las incorporaciones y los recursos de terceros de carga diferida se completan después de que se termina de cargar el contenido de la página principal o cuando el usuario se desplaza hacia abajo hasta la parte de la página en la que se incluyen.

El componente de la secuencia de comandos de Next.js

El componente de la secuencia de comandos de Next.js implementa los métodos anteriores para secuenciar secuencias de comandos y proporciona una plantilla a fin de que los desarrolladores definan su estrategia de carga. Una vez que se especifique la estrategia adecuada, se cargará de manera óptima sin bloquear otros recursos críticos.

El componente de la secuencia de comandos se basa en la etiqueta HTML <script> y proporciona una opción para establecer la prioridad de carga de las secuencias de comandos de terceros mediante el atributo de estrategia.

// Example for beforeInteractive:
<Script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

El atributo de estrategia puede tener tres valores.

  1. beforeInteractive: Esta opción se puede usar para secuencias de comandos críticas que se deben ejecutar antes de que la página se vuelva interactiva. Next.js garantiza que esas secuencias de comandos se inserten en el HTML inicial del servidor y se ejecuten antes que otro JavaScript autoempaquetado. La administración de consentimiento, las secuencias de comandos de detección de bots o las bibliotecas auxiliares necesarias para procesar contenido fundamental son buenas opciones para esta estrategia.

  2. afterInteractive: Esta es la estrategia predeterminada que se aplica y equivale a cargar una secuencia de comandos con el atributo de aplazamiento. Debe usarse para secuencias de comandos que el navegador pueda ejecutar después de que la página sea interactiva; por ejemplo, secuencias de comandos de Analytics. Next.js inserta estas secuencias de comandos en el lado del cliente y se ejecutan después de que se hidrata la página. Por lo tanto, a menos que se especifique lo contrario, Next.js aplaza todas las secuencias de comandos de terceros definidas con el componente Script, lo que proporciona una configuración predeterminada segura.

  3. lazyOnload: Esta opción se puede usar para realizar una carga diferida de secuencias de comandos de baja prioridad cuando el navegador está inactivo. La funcionalidad proporcionada por esas secuencias de comandos no es necesaria inmediatamente después de que la página se vuelve interactiva, por ejemplo, el chat o complementos para redes sociales.

Los desarrolladores pueden especificar la estrategia para indicarle a Next.js de qué manera su aplicación usa una secuencia de comandos. Esto permite que el framework aplique optimizaciones y prácticas recomendadas para cargar la secuencia de comandos y, al mismo tiempo, garantiza la mejor secuencia de carga.

Con el componente de secuencia de comandos, los desarrolladores pueden colocar una secuencia de comandos de terceros en cualquier lugar de la aplicación para los terceros que se carguen más tarde y en el nivel del documento para las secuencias de comandos críticas. Esto implica que el componente de la secuencia de comandos puede ubicarse junto al componente mediante la secuencia de comandos. Después de la hidratación, la secuencia de comandos se insertará en el encabezado del documento renderizado inicialmente o en la parte inferior del cuerpo, según la estrategia utilizada.

Medición del impacto

Usamos las plantillas para la app de comercio de Next.js y el blog de inicio a fin de crear dos apps de demostración que ayudaran a medir el impacto de incluir secuencias de comandos de terceros. Los terceros que suelen usarse en Google Tag Manager y las incorporaciones de redes sociales se incluyeron directamente en las páginas de estas apps al principio y, luego, a través del componente Secuencia de comandos. Luego, comparamos el rendimiento de estas páginas en WebPageTest.

Secuencias de comandos de terceros en una app de comercio de Next.js

Se agregaron secuencias de comandos de terceros a la plantilla de la app de comercio para la demostración, como se muestra a continuación.

Antes Después
Google Tag Manager con el modo asíncrono Componente de secuencia de comandos con estrategia = afterInteractive para ambas secuencias de comandos
Botón Seguir en Twitter sin asíncrono ni aplazamiento
Configuración de secuencias de comandos y componentes de secuencias de comandos para la demostración 1 con 2 secuencias de comandos

En la siguiente comparación, se muestra el progreso visual de ambas versiones del kit de inicio de comercio de Next.js. Como se ve, LCP se produce casi 1 segundo antes con el componente de secuencia de comandos habilitado con la estrategia de carga correcta.

Comparación de tiras de película que muestra una mejora en el LCP

Secuencias de comandos de terceros en un blog de Next.js

Se agregaron secuencias de comandos de terceros a la aplicación de blog de demostración como se indica a continuación.

Antes Después
Google Tag Manager con el modo asíncrono Componente de secuencia de comandos con estrategia = lazyonload para cada una de las cuatro secuencias de comandos
Botón Seguir en Twitter con modo asíncrono
Botón Suscribirse de YouTube sin función asíncrona o aplazamiento
Botón Seguir en LinkedIn sin acceso asincrónico o aplazamiento
Configuración de secuencias de comandos y componentes de secuencias de comandos para la demostración 2 con 4 secuencias de comandos
Video que muestra el progreso de carga de la página de índice con y sin el componente de secuencia de comandos. Hay una mejora de 0.5 segundos en el FCP con el componente de secuencia de comandos.

Como se ve en el video, el First Contentful Paint (FCP) ocurre a los 0.9 segundos en la página sin el componente Secuencia de comandos y a los 0.4 segundos con el de Secuencia de comandos.

Qué sigue para el componente Secuencia de comandos

Si bien las opciones de estrategia para afterInteractive y lazyOnload ofrecen un control significativo sobre las secuencias de comandos que bloquean la renderización, también estamos explorando otras opciones que aumentarían la utilidad del componente de secuencia de comandos.

Usa trabajadores web

Los trabajadores web se pueden usar para ejecutar secuencias de comandos independientes en subprocesos en segundo plano que pueden liberar el subproceso principal a fin de que se encargue del procesamiento de las tareas de la interfaz de usuario y mejore el rendimiento. Los trabajadores web son los más adecuados para transferir el procesamiento de JavaScript, en lugar del trabajo de la IU, fuera del subproceso principal. Las secuencias de comandos que se usan para marketing o asistencia al cliente, que en general no interactúan con la IU, pueden ser buenas candidatas para ejecutarse en un subproceso en segundo plano. Se puede usar una biblioteca de terceros liviana (PartyTown) para aislar tales secuencias de comandos en un trabajador web.

Con la implementación actual del componente de secuencia de comandos Next.js, te recomendamos diferir estas secuencias de comandos en el subproceso principal mediante la configuración de la estrategia en afterInteractive o lazyOnload. En el futuro, proponemos presentar una nueva opción de estrategia, 'worker', que permitirá que Next.js use PartyTown o una solución personalizada para ejecutar secuencias de comandos en trabajadores web. Son bienvenidas los comentarios de los desarrolladores sobre esta RFC.

Minimizar CLS

Las incorporaciones de terceros, como anuncios, videos o feeds de redes sociales, pueden provocar cambios en el diseño cuando se realizan cargas diferidas. Esto afecta la experiencia del usuario y la métrica Cambio de diseño acumulado (CLS) de la página. CLS se puede minimizar especificando el tamaño del contenedor en el que se cargará la incorporación.

El componente de secuencia de comandos se puede usar para cargar incorporaciones que pueden provocar cambios de diseño. Estamos considerando ampliarlo para proporcionar opciones de configuración que ayuden a reducir el CLS. Podría estar disponible dentro del componente de la secuencia de comandos o como un componente complementario.

Componentes del wrapper

La sintaxis y la estrategia de carga para incluir secuencias de comandos populares de terceros, como Google Analytics o Google Tag Manager (GTM), suele ser fija. Estos se pueden encapsular aún más en componentes wrapper individuales para cada tipo de secuencia de comandos. Solo un conjunto mínimo de atributos específicos de la aplicación (como el ID de seguimiento) estará disponible para los desarrolladores. Los componentes de wrapper ayudarán a los desarrolladores con lo siguiente:

  1. Facilite la inclusión de etiquetas de secuencias de comandos populares.
  2. Garantizar que el marco de trabajo utilice la estrategia óptima de forma interna.

Conclusión

Por lo general, las secuencias de comandos de terceros se crean para incluir funciones específicas en el sitio web de consumo. Para reducir el impacto de las secuencias de comandos no críticas, recomendamos diferirlas, algo que el componente de secuencia de comandos de Next.js hace de forma predeterminada. Los desarrolladores tienen la garantía de que las secuencias de comandos incluidas no retrasarán la funcionalidad crítica, a menos que apliquen explícitamente la estrategia beforeInteractive. Al igual que el componente de secuencia de comandos de Next.js, los desarrolladores de marcos de trabajo también pueden compilar estas funciones en otros frameworks. Estamos explorando activamente la posibilidad de conseguir un componente similar con el equipo de Nuxt.js. En función de los comentarios que recibimos, también esperamos mejorar aún más el componente de Script para abarcar casos de uso adicionales.

Reconocimientos

Gracias a Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner y Addy Osmani por sus comentarios sobre esta publicación.