S

super-dev — full-stack

@super-dev.app · Full-stack · ★ disponible para proyectos
12,8k suscriptores·47 vídeos·Activo desde 2017

Desarrollador full-stack .NET / Angular con perfil DevOps en Azure Cloud. También cómodo con Flutter + Firebase. Construyo productos, los despliego, los monitorizo.

Volver a los artículos
ANGULAR
ANGULAR

@defer y el nuevo control flow: menos JS al arranque

Artículo 3 de 4 — Angular 21 en la práctica
Zoneless, signals, resource(), @defer, SignalStore — el frontend moderno, de verdad.

El nuevo control flow de Angular no se limita a reemplazar *ngIf y *ngFor por una sintaxis más bonita. Combinado con @defer , cambia lo que acaba en el bundle inicial: al arrancar solo se envía el JavaScript realmente necesario para el primer renderizado, y el resto llega bajo demanda.

@if, @for, @switch

La sintaxis @ está integrada en el compilador: sin importación de directivas, y un track obligatorio en @for que obliga a pensar en la identidad de los elementos. Es ese track el que evita recrear todo en el DOM en cada cambio de lista.

TypeScript
1@if (user(); as currentUser) {
2 <p>Bonjour {{ currentUser.name }}</p>
3} @else {
4 <p>Invité</p>
5}
6
7@for (item of items(); track item.id) {
8 <li>{{ item.label }}</li>
9} @empty {
10 <li>Aucun élément</li>
11}
12
13@switch (status()) {
14 @case ('loading') { <spinner /> }
15 @case ('error') { <error-banner /> }
16 @default { <content /> }
17}

El bloque @empty de @for y el @case exhaustivo de @switch cubren casos que a menudo se olvidaban con las directivas estructurales.

@defer : cargar más tarde

@defer envuelve una parte del template cuyo código se extrae del bundle principal y se carga en un chunk separado en el momento oportuno. El disparador decide cuándo: on viewport carga cuando el bloque entra en pantalla, on interaction al primer clic/foco, on idle cuando el navegador está inactivo, on hover , o on timer .

TypeScript
1@defer (on viewport) {
2 <heavy-comments [postId]="postId()" />
3} @placeholder (minimum 200ms) {
4 <p>Commentaires</p>
5} @loading (after 100ms; minimum 300ms) {
6 <skeleton-list />
7} @error {
8 <p>Impossible de charger les commentaires.</p>
9}

Los bloques auxiliares

  • @placeholder : se renderiza antes de cualquier disparo, es el que puede llevar el trigger on viewport / on interaction . El minimum evita un flash demasiado breve.
  • @loading : durante la recuperación del chunk; after retrasa su visualización para no parpadear en una conexión rápida.
  • @error : si el chunk no carga (red cortada, por ejemplo).

También se puede precargar sin mostrar con prefetch on hover , para que el clic sea instantáneo sin penalizar el arranque.

El impacto en el bundle

Todo componente, directiva o pipe usado únicamente en un bloque @defer se extrae en su propio chunk. Una página pesada — editor de código, gráficos, mapa — puede así sacar 100 a 200 KB del bundle inicial, que solo se descargan si el usuario hace scroll hasta allí. La ganancia se mide directamente en el Largest Contentful Paint y el tiempo de interactividad. La documentación detalla cada disparador en la guía de carga diferida .

Sin embargo, hay que tener cuidado: un @defer (on viewport) colocado por encima del pliegue se dispara inmediatamente y no aporta nada. El diferido solo tiene sentido para lo que está fuera de pantalla o es condicional.

El control flow hace legible la intención, @defer hace explícito el coste. En lugar de cargar todo «por si acaso», declaras cuándo cada pieza merece su JavaScript — y el arranque se aligera solo.
super-dev — portfolio.app
// Continuar en ANGULAR
Un motor estilo DOOM en el navegador, con tres backends
11 min • 1,4k lecturas
Migrar una app Angular a zoneless + signals
8 min • 4,1k lecturas
Cargar datos con resource() y httpResource()
7 min • 3,6k lecturas