Precargar módulos

Sérgio Gomes

El desarrollo basado en módulos ofrece ventajas reales en términos de capacidad de almacenamiento lo que ayuda a reducir la cantidad de bytes que debe enviar a sus usuarios. El nivel de detalle más preciso del código también ayuda con la historia de carga, ya que te permite priorizar el código crítico en tu aplicación.

Sin embargo, las dependencias del módulo introducen un problema de carga, ya que el navegador necesita que espere a que se cargue un módulo antes de averiguar cuáles son sus dependencias. Ida solo es a través de la precarga de las dependencias, de modo que el navegador conozca todas los archivos con anticipación y puede mantener la conexión ocupada.

<link rel="preload"> es una forma de solicitar recursos de forma declarativa con anticipación antes de que el navegador los necesite.

<head>
  <link rel="preload" as="style" href="critical-styles.css">
  <link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>

Navegadores compatibles

  • Chrome: 50
  • Borde: ≤79.
  • Firefox: 85.
  • Safari: 11.1.

Origen

Esto funciona especialmente bien con recursos como las fuentes, que a menudo están ocultas dentro de los archivos CSS, a veces con varios niveles de profundidad. En ese caso, el navegador tendría que esperar varias idas y vueltas antes de descubrir que debe recuperar un archivo de fuente grande, cuando podría haber usado ese tiempo para iniciar la descarga y aprovechar todo el ancho de banda de la conexión.

<link rel="preload"> y su encabezado HTTP equivalente proporcionan una interfaz declarativa manera de informar de inmediato al navegador acerca de los archivos críticos que serán necesarios como parte de la navegación actual. Cuando el navegador ve la precarga, comienza una alta descarga de prioridad para el recurso, de modo que, cuando se necesite, ya o que ya se hayan recuperado o parcialmente allí. Sin embargo, no funciona para los módulos.

Aquí es donde las cosas se complican. Hay varios modos de credenciales recursos y, para obtener un acierto de caché, deben coincidir. De lo contrario, terminarás recuperar el recurso dos veces. No hace falta decir que la recuperación doble es malo, ya que desperdicia el ancho de banda del usuario y lo hace esperar más sin una buena razón.

Para las etiquetas <script> y <link>, puedes configurar el modo de credenciales con el crossorigin . Sin embargo, resulta que un objeto <script type="module"> sin El atributo crossorigin indica un modo de credenciales de omit, que no existe para <link rel="preload">. Esto significa que deberías Cambia el atributo crossorigin de <script> y <link> a uno. de los otros valores, y puede que no tengas una manera fácil de hacerlo si lo que de precargar es una dependencia de otros módulos.

Además, recuperar el archivo es solo el primer paso para ejecutar el código. Primero, el navegador debe analizarlo y compilarlo. Idealmente, esto también debe hacerse con anticipación, para que cuando se necesite el módulo, el código lista para ejecutarse. Sin embargo, V8 (el motor de JavaScript de Chrome) analiza y compila módulos de manera diferente a otros JavaScript. <link rel="preload"> no cualquier forma de indicar que el archivo que se carga es un módulo, de manera que todo lo que puedes hacer es cargar el archivo y colocarlo en la caché. Una vez que la secuencia de comandos se carga con un <script type="module"> (o si lo carga otro módulo), el navegador lo analiza y compila el código como un módulo de JavaScript.

En pocas palabras, sí. Al tener un tipo link específico para precargar módulos, podemos escribir HTML simple sin preocuparse por el modo de credenciales que estamos usando. El los valores predeterminados funcionan.

<head>
  <link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">

Y como el navegador ahora sabe que lo que precargas es un módulo, puede ser inteligente y analizar y compilar el módulo apenas termine de recuperarse, en lugar de esperar hasta que intente ejecutarse.

Navegadores compatibles

  • Chrome: 66.
  • Borde: ≤79.
  • Firefox: 115
  • Safari: 17.

Origen

Pero ¿qué sucede con las capacidades dependencias?

¡Qué gracioso deberías preguntar! Ciertamente, hay algo que este artículo no ha abarcado: la recursión.

La especificación <link rel="modulepreload"> en realidad permite la carga opcional, no solo el módulo solicitado, sino también todo su árbol de dependencias. Los navegadores no necesitan hacen esto, pero pueden.

¿Cuál sería la mejor solución entre navegadores para la precarga de un módulo y su ya que necesitarás el árbol de dependencias completo para ejecutar la app?

Los navegadores que eligen precargar dependencias de manera recurrente deben tener una anulación de duplicación sólida de módulos, así que, en general, la práctica recomendada sería declarar el módulo y la lista sin formato de sus dependencias y confían en que el navegador no recuperará el mismo módulo dos veces.

<head>
  <!-- dog.js imports dog-head.js, which in turn imports
       dog-head-mouth.js, which imports dog-head-mouth-tongue.js. -->
  <link rel="modulepreload" href="dog-head-mouth-tongue.mjs">
  <link rel="modulepreload" href="dog-head-mouth.mjs">
  <link rel="modulepreload" href="dog-head.mjs">
  <link rel="modulepreload" href="dog.mjs">
</head>

¿La precarga de módulos ayuda al rendimiento?

La precarga puede ayudar a maximizar el uso del ancho de banda, ya que informa al navegador lo que necesita recuperarse para que no quede atascado sin hacer nada durante esos largos recorridos. Si experimentas con módulos y tienes problemas de rendimiento debido a árboles de dependencia, crear una lista plana de precargas puede ser útil.

Dicho esto, todavía estamos trabajando en el rendimiento del módulo, así que asegúrate de que te mostramos detenidamente lo que sucede en tu aplicación con las Herramientas para desarrolladores considera agrupar tu aplicación en varios fragmentos mientras tanto. Hay muchos de módulos en curso en Chrome, por lo que estamos cada vez más cerca de brindar a los pequeñines su merecido descanso.