Contenido del curso

Nuevas Funcionalidades en Angular

Optimización de Rendimiento

afterNextRender: código seguro solo en el browser

Resumen

Cuando activas server-side rendering en Angular, aparece un problema silencioso: tu código intenta ejecutar APIs que solo existen en el navegador, como window, geolocation o setInterval, y Node.js no las reconoce. La solución pasa por un hook nuevo llamado afterNextRender, que te permite correr ese código únicamente del lado del cliente sin romper el renderizado en el servidor.

¿Por qué fallan las APIs del browser con server-side rendering?

Angular ahora ejecuta tu aplicación en dos contextos: Node.js (servidor) y el navegador (cliente). Y ahí está el detalle, no todas las APIs viven en ambos lados.

En el navegador tienes acceso a cosas como window.alert, navigator.geolocation.getCurrentPosition, conexiones Bluetooth, Progressive Web Apps y manipulación directa del DOM. En Node.js, nada de eso existe. Si tu componente intenta llamar a window durante el renderizado en servidor, obtienes el clásico error Window is not defined.

Un ejemplo claro: un componente counter que usa window.setInterval para actualizar un valor cada cierto tiempo [03:10]. Mientras navegas dentro de la app, todo funciona porque ya estás en el cliente. Pero si un usuario abre el link directo a la página about que usa ese counter, Angular intenta hacer server-side rendering, no encuentra window y la consola explota con el error.

¿Qué APIs del navegador no funcionan en server-side rendering? Todas las que dependen del entorno del browser: window, document, navigator, geolocation, Bluetooth, Web APIs de PWA y librerías que manipulen el DOM directamente.

¿Qué es afterNextRender y cómo se usa en Angular?

El hook afterNextRender se importa desde @angular/core y se ejecuta dentro del constructor del componente [05:20]. Su trabajo es simple pero clave: corre el código que pongas dentro solo cuando la aplicación ya está renderizada del lado del cliente.

Piénsalo así. El ngOnInit se ejecuta tanto en servidor como en cliente. El afterNextRender se ejecuta únicamente en el browser. Por eso es el lugar seguro para todo lo que dependa de APIs del navegador.

¿Cuándo debo usar afterNextRender en lugar de ngOnInit? Cuando tu código necesita acceder a window, document, geolocalización, o cualquier librería que lea o manipule el DOM. Si funciona en ambos contextos, deja ngOnInit.

¿Cómo migro un setInterval con window al nuevo hook?

El ajuste tiene tres pasos prácticos:

  1. Mueve la lógica con window.setInterval desde ngOnInit al afterNextRender dentro del constructor.
  2. Declara la referencia del intervalo inicializada en null como buena práctica.
  3. En ngOnDestroy, limpia el intervalo solo si la referencia existe, porque en el servidor seguirá siendo null.

Con ese patrón evitas tocar window en Node y aseguras que el clearInterval solo corra cuando realmente hay algo que limpiar [07:45]. La página recarga, el about renderiza desde el servidor sin errores y el contador sigue actualizándose en el cliente.

¿Y qué pasa con librerías de terceros que manipulan el DOM?

Aquí viene lo interesante. Muchas librerías populares de JavaScript, sobre todo las de gráficas, canvas o renderizado de audio en forma de ondas, necesitan leer el DOM para funcionar. Consultan ancho, alto, posición de elementos o crean nodos directamente.

Esas librerías también fallan en server-side rendering. La recomendación es la misma: cualquier instanciación que dependa del DOM o de un ElementRef debe vivir dentro de afterNextRender.

En la clase se migra un componente que renderiza un MP3 como ondas visuales. Originalmente usaba ngAfterViewInit para inicializar la librería. La migración consiste en mover esa lógica al constructor envuelta en afterNextRender y eliminar el ngAfterViewInit [10:30]. Resultado: la librería se instancia solo en el browser, donde tiene sentido, y el servidor renderiza el HTML base sin tropezar.

¿Por qué importa elegir bien las librerías en proyectos con SSR?

No todas las librerías están pensadas para entornos isomórficos. Antes de instalar una dependencia revisa:

  • Si depende de window, document o APIs exclusivas del browser.
  • Si manipula el DOM directamente para renderizar.
  • Si ofrece una versión compatible con Node o un modo de inicialización diferida.

Cuando la respuesta es sí a alguno de estos puntos, ya sabes el patrón: envuelve la inicialización en afterNextRender y mantén tu app funcional en ambos contextos.

Recapitulando los dos casos donde aplicar afterNextRender

Los escenarios prácticos donde este hook es obligatorio son claros:

  • APIs del navegador como window.setInterval, geolocation o cualquier capability del browser.
  • Librerías de terceros que necesiten manipular o leer el DOM para renderizar gráficas, canvas, ondas de audio o componentes visuales complejos.

El siguiente paso natural es integrar capabilities reales del navegador, como obtener la geoposición del usuario, y ver cómo se conecta toda esta lógica con hardware desde una app Angular con SSR. ¿Ya tienes pensado qué API del browser quieres integrar primero en tu proyecto? Cuéntame en los comentarios.