La mayoría de las páginas web y aplicaciones están compuestas por muchas partes diferentes. En lugar de enviar todo el código JavaScript que contiene la aplicación apenas se carga la primera página, dividir JavaScript en varios fragmentos mejora el rendimiento de la página.
En este codelab, se muestra cómo usar la división de código para mejorar el rendimiento de una aplicación simple que ordena tres números.
Medir
Como siempre, es importante medir primero el rendimiento de un sitio web antes de intentar agregar optimizaciones.
- Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa.
- Presiona "Control + Mayúsculas + J" (o "Comando + Opción + J" en Mac) para abrir DevTools.
- Haga clic en la pestaña Red.
- Selecciona la casilla de verificación Inhabilitar caché.
- Vuelve a cargar la app.
71.2 KB de JavaScript solo para ordenar algunos números en una aplicación simple. ¿Para qué me sirve esto?
En el código fuente (src/index.js
), se importa y usa la biblioteca lodash
en esta aplicación. Lodash proporciona muchas funciones útiles, pero aquí solo se usa un método del paquete.
Instalar y, luego, importar dependencias completas de terceros en las que solo se usa una pequeña parte de ellas es un error común.
Optimizar
Existen algunas formas de reducir el tamaño del paquete:
- Escribe un método de ordenamiento personalizado en lugar de importar una biblioteca de terceros
- Usa el método
Array.prototype.sort()
integrado para ordenar numéricamente - Importa el método
sortBy
solo desdelodash
y no toda la biblioteca - Descarga el código para ordenar solo cuando el usuario haga clic en el botón
Las opciones 1 y 2 son métodos perfectamente apropiados para reducir el tamaño del paquete (y probablemente tendrían más sentido para una aplicación real). Sin embargo, no se usan en este instructivo por motivos didácticos 😈.
Ambas opciones 3 y 4 ayudan a mejorar el rendimiento de esta aplicación. En las siguientes secciones de este codelab, se abordan estos pasos. Al igual que en cualquier instructivo de programación, siempre intenta escribir el código por tu cuenta en lugar de copiarlo y pegarlo.
Importa solo lo que necesitas
Se deben modificar algunos archivos para importar solo el método único de lodash
.
Para comenzar, reemplaza esta dependencia en package.json
:
"lodash": "^4.7.0",
con esto:
"lodash.sortby": "^4.7.0",
Ahora, en src/index.js
, importa este módulo específico:
import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";
Y actualiza la forma en que se ordenan los valores:
form.addEventListener("submit", e => {
e.preventDefault();
const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
const sortedValues = _.sortBy(values);
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
});
Vuelve a cargar la aplicación, abre DevTools y vuelve a mirar el panel Red.
Para esta aplicación, el tamaño del paquete se redujo por más de 4 veces con muy poco trabajo, pero todavía hay más margen por mejorar.
División de código
webpack es uno de los empaquetadores de módulos de código abierto más populares que se usan en la actualidad. En resumen, agrupa todos los módulos de JavaScript (así como otros recursos) que conforman una aplicación web en archivos estáticos que el navegador puede leer.
El único paquete que se usa en esta aplicación se puede dividir en dos fragmentos separados:
- Uno responsable del código que forma nuestra ruta inicial
- Un fragmento secundario que contiene nuestro código de ordenamiento
Con el uso de importaciones dinámicas, un fragmento secundario se puede cargar de forma diferida o cargar a pedido. En esta aplicación, el código que compone el fragmento solo se puede cargar cuando el usuario presiona el botón.
Comienza por quitar la importación de nivel superior para el método de ordenamiento en src/index.js
:
import sortBy from "lodash.sortby";
Luego, impórtalo dentro del objeto de escucha de eventos que se activa cuando se presiona el botón:
form.addEventListener("submit", e => {
e.preventDefault();
import('lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
La función import()
forma parte de una propuesta (actualmente en la etapa 3 del proceso de TC39) para incluir la capacidad de importar un módulo de forma dinámica. Webpack ya incluye compatibilidad con esto y sigue la misma sintaxis que establece la propuesta.
import()
muestra una promesa y, cuando se resuelve, se proporciona el módulo seleccionado, que se divide en un fragmento independiente. Después de que se muestra el módulo, se usa module.default
para hacer referencia a la exportación predeterminada que proporciona lodash. La promesa se encadena con otra .then
que llama a un método sortInput
para ordenar los tres valores de entrada. Al final de la cadena de promesas, .catch()
se usa para controlar los casos en los que se rechaza la promesa debido a un error.
Lo último que se debe hacer es escribir el método sortInput
al final del archivo. Debe ser una función que devuelva una función que acepte el método importado desde lodash.sortBy
. Luego, la función anidada puede ordenar los tres valores de entrada y actualizar el DOM.
const sortInput = () => {
return (sortBy) => {
const values = [
input1.valueAsNumber,
input2.valueAsNumber,
input3.valueAsNumber
];
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
};
}
Supervisar
Vuelve a cargar la aplicación por última vez y observa el panel Red nuevamente. Solo se descarga un pequeño paquete inicial apenas se carga la app.
Después de presionar el botón para ordenar los números de entrada, se recupera y ejecuta el fragmento que contiene el código de ordenamiento.
¡Observa cómo se siguen ordenando los números!
Conclusión
La división de código y la carga diferida pueden ser técnicas muy útiles para reducir el tamaño del paquete inicial de tu aplicación, lo que puede generar directamente tiempos de carga de páginas mucho más rápidos. Sin embargo, debes considerar algunos aspectos importantes antes de incluir esta optimización en tu aplicación.
Carga diferida de la IU
Cuando se cargan de forma diferida módulos de código específicos, es importante considerar cómo sería la experiencia para los usuarios con conexiones de red más débiles. Dividir y cargar un fragmento de código muy grande cuando un usuario envía una acción puede hacer que parezca que la aplicación dejó de funcionar, por lo que te recomendamos que muestres algún tipo de indicador de carga.
Carga diferida de módulos de nodos de terceros
No siempre es el mejor enfoque para cargar de forma diferida dependencias de terceros en tu aplicación, y depende de dónde las uses. Por lo general, las dependencias de terceros se dividen en un paquete vendor
independiente que se puede almacenar en caché, ya que no se actualizan con tanta frecuencia. Obtén más información sobre cómo SplitChunksPlugin puede ayudarte a hacerlo.
Carga diferida con un framework de JavaScript
Muchos frameworks y bibliotecas populares que usan webpack proporcionan abstracciones para facilitar la carga diferida que usar importaciones dinámicas en medio de la aplicación.
- Carga diferida de módulos con Angular
- División de código con React Router
- Carga diferida con Vue Router
Aunque es útil comprender cómo funcionan las importaciones dinámicas, siempre usa el método que recomienda tu framework o biblioteca para cargar módulos específicos de manera diferida.
Precarga y carga previa
Siempre que sea posible, aprovecha las sugerencias del navegador, como <link rel="preload">
o <link rel="prefetch">
, para intentar cargar módulos críticos con mayor rapidez. webpack admite ambas sugerencias mediante el uso de comentarios mágicos en las instrucciones de importación. Esto se explica con más detalle en la guía Precarga los fragmentos críticos.
Carga diferida más que código
Las imágenes pueden representar una parte importante de una aplicación. La carga diferida de los elementos que se encuentran debajo de la mitad inferior de la página o fuera del viewport del dispositivo puede acelerar un sitio web. Obtén más información al respecto en la guía de Lazysizes.