Acelera la navegación en React con Quicklink

Cargar automáticamente los vínculos en la vista del puerto con un vínculo rápido para las aplicaciones de una sola página de React.

Addy Osmani
Addy Osmani
Anton Karlovskiy
Anton Karlovskiy
Demián Renzulli
Demián Renzulli

La carga previa es una técnica que permite acelerar las navegaciones, ya que se descargan los recursos para la página siguiente con anticipación. Quicklink es una biblioteca que te permite implementar esta técnica a gran escala mediante la carga previa automática de los vínculos a medida que llegan a la vista.

En las apps de varias páginas, la biblioteca carga previamente los documentos (p.ej., /article.html) de los vínculos en el viewport, de modo que, cuando el usuario haga clic en estos vínculos, se puedan obtener de la caché HTTP.

Las apps de una sola página suelen usar una técnica llamada división de código basada en rutas. Esto permite que el sitio cargue el código para una ruta determinada solo cuando el usuario navega hacia ella. Estos archivos (JS o CSS) se conocen comúnmente como “fragmentos”.

Dicho esto, en estos sitios, en lugar de precargar los documentos, las mayores mejoras de rendimiento provienen de la carga previa de estos fragmentos antes de que la página los necesite.

Lograr esto presenta algunos desafíos:

  • No es trivial determinar qué fragmentos (p.ej., article.chunk.js) están asociados con una ruta determinada (p.ej., /article) antes de aterrizar en ella.
  • No se pueden predecir los nombres de las URLs finales de estos fragmentos, ya que los agrupadores de módulos modernos suelen usar el hash a largo plazo para el control de versiones (p.ej., article.chunk.46e51.js).

En esta guía, se explica cómo Quicklink resuelve estos desafíos y te permite realizar cargas previas a gran escala en apps de una sola página de React.

Determina los fragmentos asociados con cada ruta

Uno de los componentes principales de quicklink es webpack-route-manifest, un complemento de webpack que te permite generar un diccionario JSON de rutas y fragmentos. Esto permite que la biblioteca sepa qué archivos necesitará cada ruta de la aplicación y los obtenga previamente a medida que las rutas ingresen a la vista.

Después de integrar el complemento con el proyecto, se generará un archivo de manifiesto JSON que asocia cada ruta con sus fragmentos correspondientes:

{
  '/about': [
    {
      type: 'style',
      href: '/static/css/about.f6fd7d80.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/about.1cdfef3b.chunk.js',
    },
  ],
  '/blog': [
    {
      type: 'style',
      href: '/static/css/blog.85e80e75.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/blog.35421503.chunk.js',
    },
  ],
}

Ese archivo de manifiesto se puede solicitar de dos maneras:

  • Por URL, p.ej., https://site_url/rmanifest.json
  • A través del objeto window, en window.__rmanifest

Cargar previamente los fragmentos para las rutas en la vista del puerto

Una vez que el archivo de manifiesto esté disponible, el siguiente paso es instalar Quicklink ejecutando npm install quicklink.

Luego, se puede usar el withQuicklink() del componente de orden superior (HOC) para indicar que se debe realizar una carga previa de una ruta determinada cuando el vínculo entra en la vista.

El siguiente código pertenece a un componente App de una app de React que renderiza un menú superior con cuatro vínculos:

const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading</div>}>
        <Route path="/" exact component={Home} />
        <Route path="/blog" exact component={Blog} />
        <Route path="/blog/:title" component={Article} />
        <Route path="/about" exact component={About} />
      </Suspense>
    </main>
    <Footer />
  </div>
);

Para indicarle a Quicklink que estas rutas deben cargarse previamente a medida que ingresan a la vista, haz lo siguiente:

  1. Importa el HOC quicklink al comienzo del componente.
  2. Une cada ruta con el HOC de withQuicklink() y pásale el componente de la página y el parámetro de opciones.
const options = {
  origins: [],
};
const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading…</div>}>
        <Route path="/" exact component={withQuicklink(Home, options)} />
        <Route path="/blog" exact component={withQuicklink(Blog, options)} />
        <Route
          path="/blog/:title"
          component={withQuicklink(Article, options)}
        />
        <Route path="/about" exact component={withQuicklink(About, options)} />
      </Suspense>
    </main>
    <Footer />
  </div>
);

El HOC de withQuicklink() usa la ruta de acceso de la ruta como clave para obtener sus fragmentos asociados a partir de rmanifest.json. De forma interna, a medida que aparecen vínculos en la vista, la biblioteca inserta una etiqueta <link rel="prefetch"> en la página por cada fragmento para que se puedan realizar una carga previa. El navegador solicitará los recursos precargados con la prioridad más baja y los mantendrá en la Caché HTTP durante 5 minutos. Después de ese plazo, se aplicarán las reglas cache-control del recurso. Como resultado de esto, cuando un usuario haga clic en un vínculo y se mueva a una ruta determinada, los fragmentos se recuperarán de la caché, lo que mejora en gran medida el tiempo que lleva procesar esa ruta.

Conclusión

La carga previa puede mejorar en gran medida los tiempos de carga para navegaciones futuras. En las apps de una página de React, esto se puede lograr cargando los fragmentos asociados con cada ruta, antes de que el usuario llegue a ellos. La solución de Quicklink para la SPA de React usa webpack-route-manifest para crear un mapa de rutas y fragmentos con el objetivo de determinar qué archivos se deben cargar previamente cuando un vínculo entra en la vista. Implementar esta técnica en todo tu sitio puede mejorar en gran medida las navegaciones hasta el punto de hacer que parezcan instantáneas.