Un paquete de Next.js para administrar bibliotecas de terceros

En 2021, el equipo de Chrome Aurora introdujo el componente de Script para mejorar el rendimiento de carga de las secuencias de comandos de terceros en Next.js. Desde su lanzamiento, expandimos sus capacidades para facilitar y agilizar la carga de recursos de terceros para los desarrolladores.

En esta entrada de blog, se proporciona una descripción general de las funciones más recientes que lanzamos, en particular la biblioteca @next/third-parties, y un resumen de las iniciativas futuras.

Implicaciones de rendimiento de las secuencias de comandos de terceros

El 41% de todas las solicitudes de terceros en los sitios Next.js son secuencias de comandos. A diferencia de otros tipos de contenido, las secuencias de comandos pueden tardar bastante tiempo en descargarse y ejecutarse, lo que puede bloquear la renderización y retrasar la interactividad del usuario. Los datos del Informe sobre la experiencia del usuario en Chrome (CrUX) muestran que los sitios de Next.js que cargan más secuencias de comandos de terceros tienen tasas de aprobación más bajas de Interaction to Next Paint (INP) y Largest Contentful Paint (LCP).

Gráfico de barras que muestra una disminución en el porcentaje de Next.js que obtuvo buenas puntuaciones de INP y LCP en proporción a la cantidad de terceros cargados
Informe CrUX de diciembre de 2023 (110,823 sitios)

La correlación observada en este gráfico no implica causalidad. Sin embargo, los experimentos locales proporcionan evidencia adicional de que las secuencias de comandos de terceros tienen un impacto significativo en el rendimiento de la página. Por ejemplo, en el siguiente gráfico, se comparan varias métricas de labs cuando se agrega un contenedor de Google Tag Manager, que contiene 18 etiquetas seleccionadas al azar, a Taxonomy, una app popular de ejemplo de Next.js.

Gráfico de barras que muestra la diferencia en varias métricas de lab cuando un sitio se carga con y sin Google Tag Manager
WebPageTest (móvil 4G - Virginia, EE.UU.)

La documentación de WebPageTest proporciona detalles sobre cómo se miden estos tiempos. A simple vista, está claro que el contenedor de GTM afecta a todas las métricas de este lab. Por ejemplo, el Tiempo de bloqueo total (TBT), un proxy de lab útil que se aproxima al INP, experimentó un aumento de casi 20 veces.

Componente de secuencia de comandos

Cuando enviamos el componente <Script> en Next.js, nos aseguramos de ingresarlo a través de una API fácil de usar que se asemeja mucho al elemento tradicional <script>. Si lo usas, los desarrolladores pueden ubicar una secuencia de comandos de terceros en cualquier componente de su aplicación, y Next.js se encargará de secuenciar la secuencia de comandos una vez que se hayan cargado los recursos críticos.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Decenas de miles de aplicaciones de Next.js, incluidos sitios populares como Patreon, Target y Notion, usan el componente <Script>. A pesar de su eficacia, algunos desarrolladores expresaron inquietudes sobre los siguientes aspectos:

  • Dónde colocar el componente <Script> en una app de Next.js mientras cumples con las diferentes instrucciones de instalación de diferentes proveedores externos (experiencia para desarrolladores)
  • La estrategia de carga más adecuada para diferentes secuencias de comandos de terceros (experiencia del usuario) es la más adecuada.

Para abordar ambos problemas, lanzamos @next/third-parties, una biblioteca especializada que ofrece un conjunto de componentes optimizados y utilidades personalizadas para terceros populares.

Experiencia para desarrolladores: Cómo facilitar la administración de bibliotecas de terceros

Muchas secuencias de comandos de terceros se usan en un porcentaje significativo de los sitios de Next.js (el más popular es Google Tag Manager). El 66% de los sitios usa respectivamente. @next/third-parties se basa en el componente <Script> mediante la introducción de wrappers de nivel superior diseñados para simplificar el uso de estos casos de uso comunes.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics, otra secuencia de comandos de terceros muy usada (el 52% de los sitios Next.js), también tiene un componente propio dedicado.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties simplifica el proceso de carga de secuencias de comandos de uso general, pero también amplía nuestra capacidad de desarrollar utilidades para otras categorías de terceros, como las incorporaciones. Por ejemplo, las incorporaciones de Google Maps y YouTube se utilizan en el 8% y el 4% de los sitios web de Next.js, respectivamente. También hemos incluido componentes para que sean más fáciles de cargar.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Experiencia del usuario: Cómo lograr que las bibliotecas de terceros se carguen más rápido

En un mundo perfecto, todas las bibliotecas de terceros ampliamente adoptadas se optimizarían por completo, lo que haría que las abstracciones que mejoren su rendimiento no fueran necesarias. Sin embargo, hasta que eso se haga realidad, podemos tratar de mejorar la experiencia del usuario cuando se integra a través de frameworks populares, como Next.js. Podemos experimentar con diferentes técnicas de carga, asegurarnos de que las secuencias de comandos estén secuenciadas de manera correcta y, en última instancia, compartir nuestros comentarios con proveedores externos para fomentar los cambios ascendentes.

Pensemos en las incorporaciones de YouTube, por ejemplo. Algunas implementaciones alternativas tienen un rendimiento mucho mejor que la incorporación nativa. Actualmente, el componente <YouTubeEmbed> exportado por @next/third-parties usa lite-youtube-embed, que, cuando se muestra en una comparación de Next.js de "Hello, World", se carga mucho más rápido.

GIF que muestra una comparación de la carga de página entre el componente de incorporación de YouTube y un iframe normal de YouTube
WebPageTest (móvil 4G - Virginia, EE.UU.)

De manera similar, en Google Maps, incluimos loading="lazy" como atributo predeterminado para la incorporación para garantizar que el mapa solo se cargue cuando se encuentre a cierta distancia del viewport. Esto puede parecer un atributo obvio para incluir, especialmente porque la documentación de Google Maps lo incluye en su fragmento de código de ejemplo, pero solo el 45% de los sitios de Next.js que incorporan Google Maps usan loading="lazy".

Ejecuta secuencias de comandos de terceros en un trabajador web

Una técnica avanzada que exploramos en @next/third-parties es facilitar la descarga de las secuencias de comandos de terceros a un trabajador web. Esta función, que se populariza en bibliotecas como Partytown, puede reducir en gran medida el impacto de las secuencias de comandos de terceros en el rendimiento de la página, ya que se reubican por completo fuera del subproceso principal.

En el siguiente GIF animado, se muestran las variaciones en las tareas largas y el tiempo de bloqueo del subproceso principal cuando se aplican diferentes estrategias de <Script> a un contenedor de GTM dentro de un sitio de Next.js. Ten en cuenta que, si bien el cambio entre las opciones de estrategia solo retrasa el momento en que se ejecutan estas secuencias de comandos, su reubicación a un trabajador web elimina por completo su tiempo en el subproceso principal.

GIF que muestra diferencias en el tiempo de bloqueo del subproceso principal para las distintas estrategias de secuencias de comandos
WebPageTest (móvil 4G - Virginia, EE.UU.)

En este ejemplo específico, trasladar la ejecución del contenedor de GTM y las secuencias de comandos de etiquetas asociadas a un trabajador web redujo el TBT en un 92%.

Vale la pena señalar que, si no se administra con cuidado, esta técnica puede romper muchas secuencias de comandos de terceros de forma silenciosa, lo que dificulta la depuración. En los próximos meses, validaremos si algún componente de terceros que ofrece @next/third-parties funciona correctamente cuando se ejecuta en un trabajador web. Si es así, trabajaremos para proporcionar una forma fácil y opcional de que los desarrolladores usen esta técnica.

Próximos pasos

En el proceso de desarrollo de este paquete, se hizo evidente que era necesario centralizar las recomendaciones de carga de terceros para que otros frameworks también pudieran beneficiarse de las mismas técnicas subyacentes utilizadas. Esto nos llevó a compilar Terceros Capital, una biblioteca que usa JSON para describir técnicas de carga de terceros, que en la actualidad sirve como base para @next/third-parties.

En los próximos pasos, seguiremos enfocándonos en mejorar los componentes proporcionados para Next.js y en ampliar nuestros esfuerzos para incluir utilidades similares en otros frameworks y plataformas de CMS populares. Actualmente, trabajamos en colaboración con los encargados de mantenimiento de Nuxt y planeamos lanzar utilidades de terceros similares adaptadas a su ecosistema en un futuro cercano.

Si @next/third-parties es compatible con uno de los terceros que usas en tu app de Next.js, instala el paquete y pruébalo. Nos encantaría recibir tus comentarios sobre GitHub.