La carga de recursos grandes de JavaScript afecta la velocidad de la página de forma significativa. Dividiendo tu JavaScript en fragmentos más pequeños y descargando solo lo necesario para para funcionar durante el inicio puede mejorar en gran medida la carga de tu página la capacidad de respuesta, lo que, a su vez, puede mejorar la Interacción con el siguiente elemento de tu página Pintura (INP).
A medida que una página descarga, analiza y compila archivos JavaScript grandes, puede que no responden durante períodos. Los elementos de la página son visibles, ya que son parte del código HTML inicial de una página y tiene el estilo CSS. Sin embargo, dado que el código JavaScript necesarios para potenciar esos elementos interactivos, así como otros scripts cargados por la página, es posible que analicemos y ejecuten el código JavaScript para que funcionen. El resultado es que el usuario puede sentir que la interacción fue significativamente retrasado o incluso roto por completo.
Esto suele suceder porque se bloquea el subproceso principal, ya que se analiza JavaScript. y se compilan en el subproceso principal. Si este proceso lleva demasiado tiempo, es posible que los elementos de página no respondan con la rapidez suficiente a las entradas del usuario. Una solución para esto es cargar solo el JavaScript necesario para que la página funcione, mientras que Diferir otro JavaScript para que se cargue más adelante mediante una técnica conocida como código la división. Este módulo se centra en la última de estas dos técnicas.
Reduce el análisis y la ejecución de JavaScript durante el inicio a través de la división de código
Lighthouse muestra una advertencia cuando la ejecución de JavaScript tarda más de 2 segundos. segundos y falla cuando tarda más de 3.5 segundos. JavaScript excesivo el análisis y la ejecución es un posible problema en cualquier punto de la página ya que tiene el potencial de aumentar el retraso de entrada de una interacción si el momento en que el usuario interactúa con la página coincide con el momento se incluyen las tareas del subproceso principal responsables de procesar y ejecutar JavaScript. en ejecución.
Más que eso, la ejecución y el análisis excesivos de JavaScript son problemático durante la carga inicial de la página, ya que este es el punto en la página en el ciclo de vida de la página que es muy probable que los usuarios interactúen con ella. De hecho, El tiempo de bloqueo total (TBT), una métrica de capacidad de respuesta a la carga, está altamente correlacionado con INP, lo que sugiere que los usuarios tienen una alta tendencia a intentar interactuar durante la carga inicial de la página.
La auditoría de Lighthouse que informa el tiempo dedicado a ejecutar cada archivo JavaScript que tu página solicita es útil, ya que puede ayudarte a identificar exactamente qué Las secuencias de comandos pueden ser candidatas para la división de código. Luego, puedes ir más allá Con la herramienta de cobertura de las Herramientas para desarrolladores de Chrome a fin de identificar exactamente qué partes de el código JavaScript de una página no se usa durante la carga.
La división de código es una técnica útil que puede reducir el JavaScript inicial de una página cargas útiles útiles. Te permite dividir un paquete de JavaScript en dos partes:
- El código JavaScript necesario al cargar la página y, por lo tanto, no se puede cargar en ninguna otra tiempo.
- JavaScript restante que se puede cargar más adelante, con mayor frecuencia cuando el usuario interactúa con un elemento interactivo determinado en la página.
La división de código se puede realizar con la sintaxis import()
dinámica. Esta
sintaxis, a diferencia de los elementos <script>
, que solicitan un determinado recurso JavaScript
durante el inicio; envía una solicitud de un recurso de JavaScript más adelante.
ciclo de vida de la página.
document.querySelectorAll('#myForm input').addEventListener('blur', async () => {
// Get the form validation named export from the module through destructuring:
const { validateForm } = await import('/validate-form.mjs');
// Validate the form:
validateForm();
}, { once: true });
En el fragmento de JavaScript anterior, el módulo validate-form.mjs
es
descargar, analizar y ejecutar solo cuando un usuario enumera cualquiera de los elementos de un formulario
<input>
. En esta situación, el recurso JavaScript responsable de
que impulsa la lógica de validación del formulario solo se involucra en la página cuando
y qué es más probable que se use realmente.
Los agrupadores de JavaScript, como webpack, Parcel, Rollup y esbuild, se pueden
que está configurado para dividir paquetes de JavaScript en fragmentos más pequeños
encontrar una llamada dinámica import()
en tu código fuente. La mayoría de estas herramientas
esta acción se realizará automáticamente, pero esbuild en particular requiere que habilites esta
la optimización de las conversiones.
Notas útiles sobre la división de código
Mientras que la división de código es un método eficaz para reducir la contención del subproceso principal durante la carga inicial de la página, resulta útil tener en cuenta algunos aspectos si decides auditar el código fuente de JavaScript para las oportunidades de división del código.
Si puedes, usa un agrupador
Es una práctica común que los desarrolladores usen módulos de JavaScript durante el de desarrollo de software. Es una excelente mejora en la experiencia del desarrollador mejora la legibilidad y el mantenimiento del código. Sin embargo, hay algunas Características de rendimiento deficientes que pueden generarse al enviar JavaScript módulos a producción.
Lo más importante es que debes usar un agrupador para procesar y optimizar el código fuente el código, incluidos los módulos que quieres dividir en el código. Los empaquetadores son muy eficaces para no solo aplicar optimizaciones al código fuente de JavaScript, bastante eficaz para equilibrar las consideraciones de rendimiento, como el tamaño del paquete frente al índice de compresión. La eficacia de la compresión aumenta con el tamaño del paquete, pero los agrupadores también intentan garantizar que no sean tan grandes como para tareas largas debido a la evaluación de los guiones.
Los agrupadores también evitan el problema de enviar una gran cantidad de módulos sin agrupar
a través de la red. Las arquitecturas que usan módulos de JavaScript suelen tener conjuntos
árboles de módulos complejos. Cuando los árboles de módulos no están agrupados, cada módulo representa una
una solicitud HTTP separada y la interactividad en tu app web puede retrasarse si
no agrupas módulos. Si bien es posible utilizar el
Sugerencia de recursos <link rel="modulepreload">
para cargar árboles de módulos grandes lo antes
posible, los paquetes de JavaScript siguen siendo preferibles a los de un rendimiento de carga
punto de vista.
No inhabilites la compilación de transmisión por accidente
El motor de JavaScript V8 de Chromium ofrece una serie de optimizaciones listas para usar para asegurarte de que el código JavaScript de producción se cargue de la manera más eficiente posible. Una de estas optimizaciones se conoce como compilación de transmisión, que, al igual que análisis incremental de HTML transmitido al navegador (compila fragmentos transmitidos de JavaScript a medida que llegan desde la red.
Hay un par de formas de asegurarse de que la compilación de transmisión se realice aplicación web en Chromium:
- Transforma tu código de producción para evitar usar módulos de JavaScript. Envasadores transformar tu código fuente de JavaScript en función de un destino de compilación el objetivo suele ser específico de un entorno determinado. V8 aplicará la transmisión compilación a cualquier código de JavaScript que no use módulos, y puedes configurar tu agrupador para transformar el código del módulo de JavaScript en una sintaxis que no use módulos de JavaScript ni sus funciones.
- Si quieres enviar módulos de JavaScript a producción, usa el
.mjs
. Ya sea que tu JavaScript de producción use módulos, hay Falta de tipo de contenido especial para JavaScript que usa módulos en comparación con JavaScript que no lo hace. En lo que concierne a V8, debes inhabilitar la transmisión de contenido. compilación cuando envías módulos de JavaScript en producción con.js
. Si usas la extensión.mjs
para los módulos de JavaScript, V8 puede asegurarte de que la compilación de transmisión para código JavaScript basado en módulos no sea está roto.
No dejes que estas consideraciones te desanimen de usar la división de código. Programación la división es una manera eficaz de reducir las cargas útiles iniciales de JavaScript para los usuarios pero si usas un agrupador y sabes cómo preservar la transmisión de V8 de compilación, puedes asegurarte de que tu código JavaScript de producción sea rápido tanto como sea posible.
Demostración de importación dinámica
webpack
webpack se envía con un complemento llamado SplitChunksPlugin
, que te permite
configurar la forma en que el agrupador divide los archivos JavaScript. webpack reconoce tanto
sentencias import()
dinámicas y import
estáticas. El comportamiento de
SplitChunksPlugin
se puede modificar especificando la opción chunks
en su
actual:
chunks: async
es el valor predeterminado y hace referencia a llamadas dinámicasimport()
.chunks: initial
hace referencia a llamadas estáticasimport
.chunks: all
abarca las importaciones dinámicasimport()
y estáticas, lo que te permite para compartir fragmentos entre las importacionesasync
yinitial
.
De forma predeterminada, cada vez que webpack encuentra una sentencia import()
dinámica. it
crea un fragmento separado para ese módulo:
/* main.js */
// An application-specific chunk required during the initial page load:
import myFunction from './my-function.js';
myFunction('Hello world!');
// If a specific condition is met, a separate chunk is downloaded on demand,
// rather than being bundled with the initial chunk:
if (condition) {
// Assumes top-level await is available. More info:
// https://v8.dev/features/top-level-await
await import('/form-validation.js');
}
La configuración predeterminada de webpack para el fragmento de código anterior genera dos fragmentos separados:
- El fragmento
main.js
, que webpack clasifica como un fragmentoinitial
, que Incluye los módulosmain.js
y./my-function.js
. - El fragmento
async
, que incluye soloform-validation.js
(que contiene un hash de archivo en el nombre del recurso, si está configurado). Este fragmento solo se descargó sicondition
es verdadero.
Esta configuración te permite diferir la carga del fragmento form-validation.js
hasta
es realmente necesario. Esto puede mejorar la capacidad de respuesta de carga al reducir las secuencias de comandos
evaluación durante la carga inicial de la página. Descarga y evaluación de la secuencia de comandos
para el fragmento form-validation.js
se produce cuando se cumple una condición específica, en
en cuyo caso, se descarga el módulo importado de forma dinámica. Un ejemplo podría ser un
condición en la que un polyfill solo se descarga en un navegador en particular, o bien,
En el ejemplo anterior, el módulo importado es necesario para la interacción del usuario.
Por otro lado, si cambias la configuración de SplitChunksPlugin
para especificar
chunks: initial
garantiza que el código se divida solo en los fragmentos iniciales. Son
como los que se importan estáticamente o que se enumeran en el archivo entry
de webpack
propiedad. Si observas el ejemplo anterior, el fragmento resultante sería una
combinación de form-validation.js
y main.js
en un solo archivo de secuencia de comandos,
lo que puede empeorar el rendimiento de carga inicial de la página.
Las opciones de SplitChunksPlugin
también se pueden configurar para separar elementos más grandes
secuencias de comandos en varias más pequeñas, por ejemplo, mediante la opción maxSize
para indicar a webpack que divida los fragmentos en archivos separados si superan el límite
especificadas por maxSize
. Dividir los archivos de secuencia de comandos grandes en archivos más pequeños
mejorar la capacidad de respuesta de la carga, como, en algunos casos, la evaluación de secuencias de comandos con uso intensivo de CPU
el trabajo se divide en tareas más pequeñas, que tienen menos probabilidades de bloquear el trabajo
subproceso durante períodos más prolongados.
Además, generar archivos JavaScript más grandes también significa que las secuencias de comandos tienen más probabilidades de sufrir invalidación de caché. Por ejemplo, si envías un secuencia de comandos grande con framework y código propio de la aplicación, toda la un paquete se puede invalidar si solo se actualiza el framework, pero no hay nada más el recurso empaquetado.
Por otro lado, los archivos de secuencia de comandos más pequeños aumentan la probabilidad de que se muestre el visitante recupera los recursos de la caché, lo que hace que la página se cargue más rápido en visitas repetidas. Sin embargo, los archivos más pequeños se benefician menos de la compresión que los más grandes y puede aumentar el tiempo de ida y vuelta de red en cargas de páginas con una en la caché del navegador. Se debe tener cuidado para lograr un equilibrio entre el almacenamiento en caché la eficiencia, la eficacia de la compresión y el tiempo de evaluación de los guiones.
Demostración de webpack
Demostración de SplitChunksPlugin
de webpack
Ponga a prueba sus conocimientos
El tipo de sentencia import
que se usa cuando se realiza código
la división?
import()
dinámicoimport
.
¿Qué tipo de sentencia import
debe estar en la parte superior.
de un módulo de JavaScript y en ninguna otra ubicación?
import()
dinámicoimport
.
Cuando se usa SplitChunksPlugin
en webpack, ¿cuál es la
diferencia entre un bloque de async
y un
¿Bloque de initial
?
async
se cargan con import()
dinámico.
y los fragmentos initial
se cargan mediante
import
async
se cargan con import
estático.
y initial
los fragmentos se cargan usando recursos
import()
A continuación: Carga imágenes y elementos <iframe>
de forma diferida
Aunque suele ser un recurso bastante costoso, JavaScript no es el
el único tipo de recurso del que puedes diferir la carga. Imagen y elementos <iframe>
son recursos potencialmente costosos en sí mismos. Al igual que JavaScript,
Puede diferir la carga de imágenes y elementos <iframe>
mediante una carga diferida
los cambios, lo que se explica en el siguiente módulo de este curso.