Angular 17 tiene una nueva y emocionante característica llamada carga diferida (RFC).
La carga diferida es una técnica que permite a las aplicaciones web cargar recursos (como scripts) solo cuando son necesarios.
En lugar de cargar todo el contenido por adelantado cuando la página se carga inicialmente, la carga diferida aplaza la carga del contenido no esencial hasta que el usuario interactúa con la página, se desplaza o llega a un punto específico de la misma.
La carga lenta mejora la experiencia del usuario, ya que reduce el tiempo de carga inicial de la página y garantiza que los usuarios puedan empezar a interactuar con la aplicación lo antes posible, mientras las partes no esenciales de la aplicación se cargan en segundo plano. Reduce el ancho de banda necesario y la carga del servidor.
En las versiones anteriores de Angular, podemos lazy-load una parte de la aplicación utilizando el Router, o podemos utilizar importaciones dinámicas y ngComponentOutlet.
En Angular 17, el equipo de Angular llevará el lazy-loading al siguiente nivel:
Angular ahora tiene un bloque de control @defer
que permite la carga perezosa del contenido del bloque.
Lazy-loading también se aplica a las dependencias del contenido del bloque: todos los componentes, directivas y pipes serán lazy-loaded, también.
En este artículo, demuestro los aspectos clave de la carga perezosa en Angular 17, tales como:
- cómo especificar una expresión lógica para activar la representación de un bloque diferido.
- cómo definir una condición de activación declarativa para activar la representación (por ejemplo, al pasar el ratón por encima), qué tipos de activación se admiten.
- cómo mostrar un marcador de posición, un estado de carga o un estado de error con bloques
@placeholder
,@loading
y@error
adicionales
cómo funciona la precarga - El código fuente completo está disponible aquí:
He utilizado Angular v17.0.0-next.8 con componentes independientes y Signals. Puedes iniciar el frontend mediante yarn run start o npm run start.
Usando @defer con una expresión lógica:
En el primer ejemplo, creo una casilla de verificación y la vinculo a la señal isCheckedDefer
. El valor por defecto de la señal es false, por lo que inicialmente la casilla de verificación no está marcada, y el contenido del bloque @defer
no se muestra. Los siguientes ejemplos son del archivo de plantilla src\app\app.component.html:
<div>
<input #checkboxDefer type="checkbox" [checked]="isCheckedDefer()" (change)="isCheckedDefer.set(checkboxDefer.checked)" id="checkboxDefer"/>
<label for="checkboxDefer">Open the network tab of the browser's developer tools, then check this checkbox to load the <strong>app-c1</strong> component</label>
</div>
<br>
@defer (when isCheckedDefer()) {
<app-c1/>
}
@placeholder {
<span>Placeholder</span>
}
@error {
<span>Error</span>
}
@loading(minimum 1s) {
<span>Loading...</span>
}
La sentencia @defer
(when expresión_logica)
{ crea un bloque @defer
con la expresión lógica. Utilizo la señal isCheckedDefer()
como expresión lógica, ya que se evalúa a un valor booleano.
He añadido tres tipos de bloque diferentes bajo el bloque @defer
, por lo que hay:
- Un bloque
@defer
, Angular lo renderiza, cuando el valor de la señalisCheckedDefer
se convierte en true. Contiene un componente hijo: - Un bloque
@placeholder
, se renderiza inicialmente, antes de que se dispare el bloque@defer
. - Cuando se activa el bloque
@defer
, Angular carga el contenido del bloque desde el servidor. Durante la carga, muestra el bloque@loading
- Si la carga falla, Angular muestra el bloque
@error
El uso de los bloques @placeholder
, @loading
y @error
es opcional, por lo que también podemos usar bloques @defer
independientes.
Veamos cómo funciona este código. Cuando abrimos la aplicación, la señal isCheckedDefer
es falsa, por lo que el bloque @defer
no se activa y el contenido del bloque @placeholder
es visible:
A continuación se muestra el contenido del bloque @defer
, el componente :
En las herramientas de desarrollador podemos ver que tras marcar la casilla, Angular ha cargado un nuevo chunk de la aplicación, que contiene el contenido del bloque @defer
:
Ahora recargamos la aplicación, borramos el contenido de la pestaña Red y bloqueamos las peticiones de red en el navegador:
Cuando marcamos la casilla de verificación, la señal isCheckedDefer
se convierte en verdadera, por lo que Angular carga el contenido del bloque @defer
. Elimina el contenido del bloque @placeholder
y muestra el contenido del bloque @loading
.
Luego la carga falla con un error de conexión de red, por lo que Angular muestra el contenido del bloque @error
:
Uso de @defer
con una condición de activación declarativa
Los bloques diferidos admiten los siguientes tipos de disparadores declarativos:
- en interacción
- al pasar el ratón
- en reposo
- en temporizador
- en viewport
¡Vamos a crear un ejemplo para todo esto!
@defer en interacción
Angular muestra el bloque on interaction
cuando el usuario interactúa con su bloque @placeholder
. Una interacción puede ser un click
, touch focus
, o eventos de input
, como keypress
:
@defer (on interaction) {
<span>Clicked</span>
}
@placeholder {
<span>Placeholder (click on it!)</span>
}
@defer on hover
Angular renderiza el bloque on hover, cuando el usuario pasa el ratón por encima de su bloque @placeholder
:
@defer (on hover) {
<span>Hovered</span>
}
@placeholder {
<span>Placeholder (hover it!)</span>
}
@defer on idle
Angular renderiza el bloque on idle, cuando el navegador alcanza un estado de reposo después de que la página ha sido cargada:
@defer (on idle) {
<span>Browser has reached an idle state</span>
}
@placeholder {
<span>Placeholder</span>
}
@defer on timer
El bloque on timer se renderiza una vez transcurrido el tiempo especificado:
@defer (on timer(5s)) {
<span>Visible after 5s</span>
}
@placeholder {
<span>Placeholder</span>
}
@defer on viewport
Angular muestra el bloque on viewport cuando el marcador de posición entra en la ventana gráfica del navegador:
@defer (on viewport) {
<app-c2 text="The block entered the viewport"/>
}
@placeholder {
<span>Placeholder</span>
}
Después de recargar la aplicación, podemos comprobar con la herramienta de inspección si el contenido del bloque @placeholder
se ha renderizado en el DOM o no:
Ahora sigue estos pasos
- cambia a la pestaña Red dentro de las herramientas de desarrollo de tu navegador
- borra el contenido de la pestaña Red
- desplázate hasta la parte inferior de la página
- Como resultado, Angular carga y renderiza el contenido del bloque
@defer
(el componente<app-c2>
):
Búsqueda previa
Junto a una condición de activación, podemos especificar una condición de prefetch
adicional:
@defer (on interaction; prefetch on hover) {
<app-c3/>
}
@placeholder {
<span>Placeholder (hover it, then click on it!)</span>
}
Vuelva a cargar la aplicación y siga estos pasos:
- borra el contenido de la pestaña Red
- pasa el ratón por encima del marcador de posición de la sección
"Prefetch
Como resultado, Angular carga el contenido del bloque@defer
, pero no se renderiza, el@placeholder
permanece visible:
A continuación, hacemos clic en el marcador de posición, y Angular renderiza el bloque prefijado (el componente <app-c3>
):
Resumen
En este artículo he mostrado algunas de las grandes novedades de Angular 17: te he enseñado cómo funcionan los nuevos bloques diferidos y cómo especificar condiciones para activar la carga y renderización del contenido de estos bloques. Espero que mi tutorial te haya resultado útil.
En la segunda parte de esta serie de artículos, te mostraré cómo funciona el nuevo flujo de control (bloques @if
, @else
, @switch
y @case
) en Angular 17