Acelera la navegación en React con Quicklink

Carga previa automática de vínculos en viewports con vínculo rápido para 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 descarga 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 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) para vínculos dentro del viewport, de modo que, cuando el usuario haga clic en estos vínculos, se puedan obtener de la caché HTTP.

Por lo general, las apps de una sola página usan una técnica llamada división de código basada en rutas. De esta manera, el sitio puede cargar el código de una ruta determinada solo cuando el usuario navega hacia ella. Estos archivos (JS, CSS) se denominan comúnmente “fragmentos”.

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

Lograr este objetivo plantea 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 llegar a ella.
  • No se pueden predecir los nombres de las URLs finales de estos fragmentos, ya que los agrupadores de módulos modernos suelen usar 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 lograr la carga previa a gran escala en apps de una sola página de React.

Determinar los fragmentos asociados con cada ruta

Uno de los componentes centrales 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 cargará previamente a medida que las rutas ingresen a la vista.

Después de integrar el complemento en el proyecto, se generará un archivo de manifiesto JSON que asocia cada ruta con los 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',
    },
  ],
}

Este archivo de manifiesto puede solicitarse 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 de las rutas en el viewport

Una vez que el archivo de manifiesto esté disponible, el siguiente paso es instalar Quicklink. Para ello, ejecuta 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 ingresa 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, sigue estos pasos:

  1. Importa el HOC quicklink al comienzo del componente.
  2. Une cada ruta con el HOC 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 withQuicklink() usa la ruta de la ruta como clave para obtener los fragmentos asociados de rmanifest.json. De forma interna, a medida que ingresan vínculos en la vista, la biblioteca inserta una etiqueta <link rel="prefetch"> en la página para cada fragmento para que se puedan cargar previamente. 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 hace clic en un vínculo y se dirige a una ruta determinada, los fragmentos se recuperan del caché, lo que mejora en gran medida el tiempo que lleva procesar esa ruta.

Conclusión

La precarga puede mejorar en gran medida los tiempos de carga para navegaciones futuras. En las apps de una sola 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 React SPA usa webpack-route-manifest a fin de crear un mapa de rutas y fragmentos, con el fin de determinar qué archivos se deben cargar previamente cuando aparece un vínculo en la vista. Si implementas esta técnica en todo tu sitio, puedes mejorar mucho las navegaciones hasta que parezcan instantáneas.