<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ricardo Chavarria</title>
    <description>The latest articles on Forem by Ricardo Chavarria (@ricardochl).</description>
    <link>https://forem.com/ricardochl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264740%2F2138d882-de52-4cee-843d-74ef071b6e4a.jpg</url>
      <title>Forem: Ricardo Chavarria</title>
      <link>https://forem.com/ricardochl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ricardochl"/>
    <language>en</language>
    <item>
      <title>Adiós Karma, Hola Vitest: El Futuro del Testing en Angular</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Fri, 27 Jun 2025 21:45:52 +0000</pubDate>
      <link>https://forem.com/ricardochl/adios-karma-hola-vitest-el-futuro-del-testing-en-angular-52h3</link>
      <guid>https://forem.com/ricardochl/adios-karma-hola-vitest-el-futuro-del-testing-en-angular-52h3</guid>
      <description>&lt;p&gt;A lo largo de los años, quienes hemos trabajado estrechamente con Angular hemos presenciado una evolución constante, tanto en el framework como en su ecosistema. Con Angular v20, se introduce uno de los avances más relevantes en el ámbito del testing: la adopción experimental de Vitest como nuevo motor de pruebas. Este cambio no solo responde a la necesidad de modernizar la experiencia de desarrollo, sino que también señala el comienzo de una transición gradual lejos de Karma, el sistema de testing que ha acompañado a Angular desde sus inicios.&lt;/p&gt;

&lt;h2&gt;
  
  
  El Adiós a un Clásico: ¿Qué Pasó con Karma?
&lt;/h2&gt;

&lt;p&gt;Durante más de una década, Karma fue el test runner por defecto en Angular, desempeñando un papel fundamental en el ecosistema. Diseñado para ejecutar pruebas en navegadores reales y adaptarse a múltiples entornos, fue una solución efectiva durante el período en que Webpack era la herramienta predominante en Angular.&lt;/p&gt;

&lt;p&gt;Sin embargo, a mediados de 2024, el equipo de Karma marcó oficialmente el proyecto como obsoleto, publicaron un aviso en su &lt;a href="https://github.com/karma-runner/karma" rel="noopener noreferrer"&gt;repositorio de GitHub&lt;/a&gt; indicando que el desarrollo activo se detiene y se recomienda buscar alternativas modernas. Ante esto, el equipo de Angular ha comenzado a ofrecer soporte experimental para Vitest a partir de Angular v20.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vitest: Testing Moderno para el Ecosistema Web
&lt;/h2&gt;

&lt;p&gt;Vitest es un test runner moderno y ultrarrápido diseñado para integrarse de forma nativa con Vite, el nuevo estándar en herramientas de desarrollo frontend. Inspirado en la experiencia de desarrollo de Jest, pero construido sobre tecnologías modernas como ES Modules, esbuild y Vite, Vitest introduce una nueva forma de escribir y ejecutar pruebas unitarias.&lt;/p&gt;

&lt;p&gt;A diferencia de herramientas tradicionales como Karma, que dependen de navegadores reales y procesos más pesados, Vitest está optimizado para el rendimiento, la simplicidad y la experiencia de desarrollador. Su ejecución en memoria, su capacidad para aprovechar el sistema de hot module replacement (HMR) de Vite y su compatibilidad con TypeScript de forma nativa, lo hacen ideal para entornos modernos como Angular, React, Vue y otros.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beneficios clave de Vitest
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rápido desde el inicio&lt;/strong&gt;: Ejecuta pruebas casi al instante gracias a su arquitectura basada en ESM y Vite.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integración nativa con Vite&lt;/strong&gt;: Aprovecha el sistema de build moderno de Vite sin configuración adicional.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mejor experiencia de desarrollo&lt;/strong&gt;: Soporta watch mode, pruebas en caliente y mensajes de error claros.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compatible con Jest&lt;/strong&gt;: Usa una API similar, facilitando la adopción o migración.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versátil&lt;/strong&gt;: Funciona en Node y con entornos simulados de navegador (como jsdom).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurando Vitest en un proyecto Angular (v20+)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instala las dependencias necesarias&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vitest jsdom &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configura &lt;code&gt;angular.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"builder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@angular/build:unit-test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tsConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsconfig.spec.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"buildTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"::development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"runner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto indica al Angular CLI que utilice Vitest como runner en lugar de Karma.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ajusta los imports en tus archivos de prueba:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ahora debes actualizar tus archivos de prueba para incluir las importaciones correctas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Ejecuta las pruebas con el comando habitual:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este comando ejecutará Vitest en modo de observación (watch), permitiendo resultados inmediatos ante cada cambio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consideraciones y Limitaciones Actuales
&lt;/h2&gt;

&lt;p&gt;Aunque la integración de Vitest en Angular es un avance prometedor, es importante tener en cuenta que el soporte aún se encuentra en fase experimental. Esto implica algunas limitaciones que los desarrolladores deben considerar antes de migrar completamente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cobertura de código&lt;/strong&gt;: Aunque Vitest soporta generación de reportes de cobertura (coverage), es necesario configurarlo explícitamente y puede requerir ajustes adicionales en proyectos Angular complejos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Depuración en navegadores reales&lt;/strong&gt;: A diferencia de Karma, que ejecuta pruebas directamente en navegadores, Vitest simula el entorno mediante jsdom. Esto es suficiente para la mayoría de pruebas unitarias, pero podría no reflejar con exactitud ciertos comportamientos específicos del navegador.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pruebas E2E&lt;/strong&gt;: Vitest no reemplaza a herramientas de pruebas de extremo a extremo como Cypress o Playwright, por lo que sigue siendo necesario usarlas para flujos de usuario completos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;La integración de Vitest en Angular marca un cambio importante en la forma en que abordamos el testing en Angular. El fin de una era con Karma y la transición hacia herramientas más modernas y rápidas no solo mejora la experiencia del desarrollador, sino que alinea Angular con las prácticas y tecnologías que ya predominan en el ecosistema frontend actual.&lt;/p&gt;

&lt;p&gt;A medida que la comunidad lo adopte y el equipo de Angular avance en su estabilización, podemos esperar más mejoras, compatibilidad avanzada con entornos reales de navegador y mayor integración con las herramientas del ecosistema.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>testing</category>
      <category>vitest</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Angular 20 y el futuro sin Zone.js: La revolución "Zoneless" ha llegado (a Developer Preview)</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Tue, 10 Jun 2025 05:45:52 +0000</pubDate>
      <link>https://forem.com/ricardochl/angular-20-y-el-futuro-sin-zonejs-la-revolucion-zoneless-ha-llegado-a-developer-preview-4k5m</link>
      <guid>https://forem.com/ricardochl/angular-20-y-el-futuro-sin-zonejs-la-revolucion-zoneless-ha-llegado-a-developer-preview-4k5m</guid>
      <description>&lt;p&gt;Si has estado siguiendo la evolución de Angular, sabrás que cada nueva versión trae consigo mejoras y optimizaciones. Pero de vez en cuando, llega una versión que no es solo una actualización, sino un verdadero punto de inflexión. &lt;strong&gt;Angular 20 es una de esas versiones&lt;/strong&gt;, y trae consigo la promoción oficial a &lt;strong&gt;Developer Preview&lt;/strong&gt; de una de las características más esperadas y transformadoras: la ejecución de aplicaciones sin Zone.js.&lt;/p&gt;

&lt;p&gt;¿Por qué tanto revuelo? Porque aunque no está listo para producción, nos invita a probar un cambio fundamental en cómo Angular gestiona la detección de cambios, abriendo la puerta a un rendimiento sin precedentes y a un código más explícito y predecible.&lt;/p&gt;

&lt;p&gt;En este artículo, vamos a desglosar qué significa "zoneless", por qué es una revolución y cómo puedes empezar a experimentar con la próxima generación de aplicaciones Angular. ¡Vamos allá!&lt;/p&gt;

&lt;h2&gt;
  
  
  El "Problema" Silencioso: ¿Qué es Zone.js y por qué queremos dejarlo atrás?
&lt;/h2&gt;

&lt;p&gt;Para entender la importancia de un Angular "zoneless", primero debemos entender qué es y qué hace &lt;strong&gt;Zone.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Desde sus inicios, Angular ha dependido de Zone.js para saber &lt;em&gt;cuándo&lt;/em&gt; debe ejecutar la detección de cambios. Zone.js es una librería que utiliza una técnica llamada "monkey-patching" para interceptar casi todas las operaciones asíncronas del navegador: &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;Promise&lt;/code&gt;, eventos del DOM (como clics), peticiones &lt;code&gt;fetch&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Cuando una de estas operaciones se completa, Zone.js notifica a Angular, que por precaución, inicia un ciclo de detección de cambios que recorre todo el árbol de componentes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Las desventajas de este enfoque son claras:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Sobrecarga de Rendimiento (Overhead):&lt;/strong&gt; La detección de cambios se ejecuta con más frecuencia de la necesaria.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Tamaño del Bundle:&lt;/strong&gt; Zone.js añade un peso extra al bundle final de tu aplicación.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;La "Magia" es Impredecible:&lt;/strong&gt; El "monkey-patching" puede causar conflictos con librerías de terceros o nuevas APIs del navegador.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Complejidad Oculta:&lt;/strong&gt; Oculta el mecanismo de reactividad. El desarrollador no tiene control explícito sobre cuándo se actualiza la UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  La Solución Elegante: ¡Hola, Detección de Cambios "Zoneless"!
&lt;/h2&gt;

&lt;p&gt;La era "zoneless" elimina por completo la dependencia de Zone.js. En su lugar, Angular adopta un modelo de reactividad mucho más fino, explícito y eficiente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El protagonista de esta historia son las Señales (Signals).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Introducidas en Angular 16, las &lt;strong&gt;Signals&lt;/strong&gt; son el pilar fundamental del futuro "zoneless". Una señal es un contenedor reactivo para un valor que puede notificar a sus consumidores cuando ese valor cambia.&lt;/p&gt;

&lt;p&gt;El nuevo modelo funciona así:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cuando el valor de un &lt;strong&gt;Signal&lt;/strong&gt; cambia, Angular sabe &lt;strong&gt;exactamente&lt;/strong&gt; qué componentes y qué partes de la vista dependen de esa signal y actualiza &lt;strong&gt;únicamente&lt;/strong&gt; esas partes. No hay un barrido completo del árbol de componentes. La actualización es local, granular y quirúrgica.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esto es un cambio de paradigma. Pasamos de un modelo de "revisar todo por si acaso" a un modelo de "actualizar solo esto porque sé que ha cambiado".&lt;/p&gt;

&lt;h3&gt;
  
  
  Aclaración Crucial: ¿Necesito "Zoneless" para usar Signals?
&lt;/h3&gt;

&lt;p&gt;Esta es una de las preguntas más importantes: ¿debo esperar a "zoneless" para empezar a usar Signals?&lt;/p&gt;

&lt;p&gt;La respuesta es un rotundo &lt;strong&gt;NO&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Puedes y debes empezar a usar Signals hoy mismo en tus aplicaciones Angular (v16+), incluso si siguen utilizando Zone.js.&lt;/strong&gt; De hecho, son dos conceptos relacionados pero independientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Signals NO necesitan Zoneless para funcionar.&lt;/strong&gt; Ya ofrecen grandes beneficios en un entorno con Zone.js, proporcionando actualizaciones de vista más rápidas y un código más reactivo.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Pero Zoneless SÍ necesita Signals.&lt;/strong&gt; Sin la "magia" de Zone.js para detectar cambios, las Signals se convierten en el mecanismo principal y explícito para que Angular sepa qué partes de la UI necesitan ser actualizadas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al usar Signals en una aplicación con Zone.js, tu código ya se vuelve más eficiente. Cuando finalmente migres a "zoneless", la transición será mucho más sencilla porque tus componentes ya estarán preparados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manos a la Obra: ¿Cómo Funciona en la Práctica?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Antes: Con Zone.js y Propiedades de Clase
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// contador.component.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-contador&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h2&amp;gt;Contador (con Zone.js)&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;Valor actual: {{ count }}&amp;lt;/p&amp;gt;
    &amp;lt;button (click)="incrementar()"&amp;gt;Incrementar&amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContadorComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;incrementar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí, cuando incrementar() se ejecuta, Zone.js intercepta el evento click, notifica a Angular y se inicia la detección de cambios que actualizará la vista.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ahora: El Futuro "Zoneless" con Signals
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;¡Nota importante!&lt;/strong&gt; La siguiente funcionalidad está en &lt;strong&gt;Developer Preview&lt;/strong&gt;. Esto significa que la API es funcional, pero podría cambiar y &lt;strong&gt;no se recomienda para aplicaciones en producción&lt;/strong&gt;. Es el momento perfecto para probarla en proyectos personales y para dar feedback valioso al equipo de Angular.&lt;/p&gt;

&lt;p&gt;Para habilitar el modo "zoneless", primero debemos configurar el arranque de nuestra aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bootstrapApplication&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideZonelessChangeDetection&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app/app.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;bootstrapApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ¡Aquí está la magia! Activamos el modo zoneless.&lt;/span&gt;
    &lt;span class="nf"&gt;provideZonelessChangeDetection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, podemos refactorizar nuestro componente para usar Signals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// contador-zoneless.component.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-contador-zoneless&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ¡Los componentes Standalone son el camino!&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h2&amp;gt;Contador (Zoneless con Signals)&amp;lt;/h2&amp;gt;
    &amp;lt;!-- Para leer el valor de una señal, la invocamos como una función --&amp;gt;
    &amp;lt;p&amp;gt;Valor actual: {{ count() }}&amp;lt;/p&amp;gt; 
    &amp;lt;button (click)="incrementar()"&amp;gt;Incrementar&amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContadorZonelessComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Creamos la señal con un valor inicial de 0&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;incrementar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Usamos .update() para modificar el valor basado en el valor anterior&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este nuevo componente, no hay Zone.js. Cuando llamamos a &lt;code&gt;this.count.update()&lt;/code&gt;, la signal notifica directamente al template, y Angular actualiza solo el párrafo &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;. Eficiencia en estado puro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beneficios Clave (y Potenciales) de la Arquitectura Zoneless
&lt;/h2&gt;

&lt;p&gt;Adoptar este nuevo enfoque traerá ventajas monumentales una vez sea estable:&lt;/p&gt;

&lt;p&gt;🚀 Rendimiento Superior: Actualizaciones increíblemente rápidas y localizadas.&lt;br&gt;
📦 Bundle Más Pequeño: Al eliminar Zone.js, reducimos el tamaño final de la aplicación.&lt;br&gt;
🧠 Código Más Predecible y Explícito: Se acaba la "magia". Tienes el control total sobre las actualizaciones.&lt;br&gt;
🤝 Mejor Interoperabilidad: Se eliminan los conflictos con librerías de terceros.&lt;/p&gt;

</description>
      <category>angular</category>
    </item>
    <item>
      <title>Resource API en Angular: La revolución declarativa de los datos asincrónicos</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Sun, 01 Jun 2025 03:54:13 +0000</pubDate>
      <link>https://forem.com/ricardochl/resource-api-en-angular-la-revolucion-declarativa-de-los-datos-asincronicos-3513</link>
      <guid>https://forem.com/ricardochl/resource-api-en-angular-la-revolucion-declarativa-de-los-datos-asincronicos-3513</guid>
      <description>&lt;h1&gt;
  
  
  Reactividad Declarativa con &lt;code&gt;resource()&lt;/code&gt;, &lt;code&gt;rxResource()&lt;/code&gt; y &lt;code&gt;httpResource()&lt;/code&gt; en Angular
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introducción: Un nuevo paradigma en la reactividad de Angular
&lt;/h2&gt;

&lt;p&gt;Angular está viviendo una de sus transformaciones más importantes desde la introducción de Ivy. Con Angular v17 y especialmente v18/v19, el framework ha empezado a adoptar un enfoque mucho más declarativo y reactivo, alejándose del tradicional modelo basado en RxJS y &lt;code&gt;async pipe&lt;/code&gt; como eje central de la reactividad.&lt;/p&gt;

&lt;p&gt;Las nuevas APIs &lt;code&gt;resource()&lt;/code&gt;, &lt;code&gt;rxResource()&lt;/code&gt; y &lt;code&gt;httpResource()&lt;/code&gt; son un ejemplo claro de este cambio. Diseñadas para manejar flujos asincrónicos de datos de forma declarativa, estas APIs permiten simplificar la lógica de datos en componentes, reducir boilerplate y aprovechar el nuevo sistema de signals de Angular.&lt;/p&gt;

&lt;p&gt;Este artículo explora a fondo estas APIs, con ejemplos prácticos y comparaciones, para ayudarte a comprender cuándo, por qué y cómo usarlas de forma efectiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;resource()&lt;/code&gt;: Reactividad declarativa con Promesas
&lt;/h2&gt;

&lt;p&gt;La función &lt;code&gt;resource()&lt;/code&gt; es la forma más sencilla de integrar flujos asincrónicos (basados en Promesas) dentro del sistema de signals de Angular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uso básico de &lt;code&gt;resource()&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Acceso a estados reactivos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta declaración permite que Angular se encargue de manejar estados de carga, cancelación, errores y la reactividad sin necesidad de suscripciones o &lt;code&gt;async pipe&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;rxResource()&lt;/code&gt;: Flujos RxJS reactivos en el mundo de Signals
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rxResource()&lt;/code&gt; permite envolver un Observable y convertirlo en una resource reactiva, combinando lo mejor de RxJS con el sistema de signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo práctico con &lt;code&gt;HttpClient&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rxResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core/rxjs-interop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rxResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/search?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ventajas de &lt;code&gt;rxResource()&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compatible con servicios existentes que retornan observables&lt;/li&gt;
&lt;li&gt;Cancelación automática cuando cambian los parámetros&lt;/li&gt;
&lt;li&gt;Integración directa con operadores de RxJS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;httpResource()&lt;/code&gt;: Declaración más simple para operaciones HTTP
&lt;/h2&gt;

&lt;p&gt;Si estás usando &lt;code&gt;HttpClient&lt;/code&gt; y necesitas una resource, &lt;code&gt;httpResource()&lt;/code&gt; simplifica la sintaxis eliminando la necesidad de definir el loader manualmente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Características clave
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Usa internamente &lt;code&gt;HttpClient&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Incluye cancelación, manejo de errores y estados reactivos&lt;/li&gt;
&lt;li&gt;Requiere menos configuración&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparación de las tres APIs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;&lt;code&gt;resource()&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;rxResource()&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fuente de datos&lt;/td&gt;
&lt;td&gt;Promesa&lt;/td&gt;
&lt;td&gt;Observable RxJS&lt;/td&gt;
&lt;td&gt;HttpClient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Estados (loading/error)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cancelación automática&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integración RxJS&lt;/td&gt;
&lt;td&gt;Parcial&lt;/td&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;Parcial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sintaxis simplificada&lt;/td&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;Alta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ideal para&lt;/td&gt;
&lt;td&gt;Carga remota&lt;/td&gt;
&lt;td&gt;Streams continuos&lt;/td&gt;
&lt;td&gt;APIs REST simples&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Casos de uso reales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Búsquedas reactivas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/search?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paginación
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paginatedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rxResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;page&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/data?page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;size=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Formularios y edición
&lt;/h3&gt;

&lt;p&gt;Puedes usar &lt;code&gt;resource().refresh()&lt;/code&gt; tras guardar los cambios para volver a cargar la data desde el servidor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;userResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ventajas frente a enfoques tradicionales
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Eliminan la necesidad de &lt;code&gt;async pipe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;No requieren &lt;code&gt;subscribe()&lt;/code&gt; manual ni destrucción de observables&lt;/li&gt;
&lt;li&gt;Simplifican la composición de lógica reactiva&lt;/li&gt;
&lt;li&gt;Mejoran la legibilidad y mantenibilidad&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Las APIs &lt;code&gt;resource()&lt;/code&gt;, &lt;code&gt;rxResource()&lt;/code&gt; y &lt;code&gt;httpResource()&lt;/code&gt; representan un cambio fundamental hacia una arquitectura declarativa y basada en signals en Angular. Aunque aún están en fase experimental, su adopción ofrece una experiencia de desarrollo moderna, con menos boilerplate, mejor manejo de estado y cancelación automática de solicitudes.&lt;/p&gt;

&lt;p&gt;Estas herramientas permiten a los desarrolladores escribir aplicaciones más limpias, predecibles y fácilmente testeables. A medida que Angular sigue evolucionando, adoptar este paradigma puede ofrecer ventajas competitivas y mayor escalabilidad en proyectos de mediano y largo plazo.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Angular se reinventa: Bienvenido a la era de Angular v18</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Thu, 23 May 2024 22:04:13 +0000</pubDate>
      <link>https://forem.com/ricardochl/angular-se-reinventa-bienvenido-a-la-era-de-angular-v18-5ac1</link>
      <guid>https://forem.com/ricardochl/angular-se-reinventa-bienvenido-a-la-era-de-angular-v18-5ac1</guid>
      <description>&lt;p&gt;La espera ha terminado. Angular v18, la última versión del popular framework de Google para desarrollo web, ha llegado para revolucionar la forma en que creamos aplicaciones web. Con un enfoque claro en la optimización del rendimiento y la introducción de nuevas características que simplifican el desarrollo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change detection - Zoneless (Experimental)
&lt;/h2&gt;

&lt;p&gt;Tradicionalmente, una librería llamada ZoneJS se ha encargado de activar la detección de cambios en Angular. Sin embargo, esta librería ha presentado ciertas desventajas en términos de rendimiento y experiencia de desarrollo. &lt;/p&gt;

&lt;p&gt;Angular v18 introduce una nueva forma de activar la detección de cambios. En lugar de depender de ZoneJS para saber cuándo es posible que algo haya cambiado, Angular ahora puede programar una detección de cambios por sí mismo. Toma en cuenta que esto está en una etapa experiemental.&lt;/p&gt;

&lt;p&gt;Para hacerlo, se agregó un nuevo programador al framework (llamado ChangeDetectionScheduler) y este programador se usa internamente para activar la detección de cambios. Este nuevo programador está habilitado de forma predeterminada en v18, incluso si usa ZoneJS. Sin embargo, el objetivo es alejarse progresivamente de ZoneJS y confiar únicamente en este nuevo planificador.&lt;/p&gt;

&lt;p&gt;Con este nuevo programador, Angular ya no depende únicamente de ZoneJS para activar la detección de cambios. De hecho, el nuevo programador activa una detección de cambios cuando se activa un host o un escucha de plantilla, cuando se adjunta o elimina una vista, cuando una tubería asíncrona detecta una nueva emisión, cuando se llama al método &lt;code&gt;markForCheck()&lt;/code&gt;, cuando se establece un valor de señal , etc. Lo hace llamando a &lt;code&gt;ApplicationRef.tick()&lt;/code&gt;internamente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experimentando con zoneless
&lt;/h3&gt;

&lt;p&gt;Puedes probar el soporte para zoneless en Angular despues de actualizar a la versión 18, solo necesitas hacer un pequeño cambio en el &lt;code&gt;boostrap&lt;/code&gt; de tu aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;bootstrapApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideExperimentalZonelessChangeDetection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al hacerlo, Angular ya no dependerá de ZoneJS para activar la detección de cambios. Así que puedes eliminar ZoneJS de tu aplicación si lo deseas (y si no tienes dependencias que dependan de él, por supuesto). En ese caso, puedes eliminar ZoneJS de los polyfills en tu archivo angular.json.&lt;/p&gt;

&lt;p&gt;Si tus componentes son compatibles con la estrategia de detección de cambios &lt;code&gt;ChangeDetectionStrategy.OnPush&lt;/code&gt; de Angular, también deberían ser en su mayoría compatibles con zoneless, lo que hará que su transición sea perfecta.&lt;/p&gt;

&lt;p&gt;De cara al futuro, un Angular sin ZoneJS abre un abanico de &lt;br&gt;
posibilidades para los desarrolladores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mayor compatibilidad:&lt;/strong&gt; Facilita la creación de micro-frontends y la interoperabilidad con otros frameworks.&lt;/li&gt;
&lt;li&gt;Rendimiento mejorado: Tiempos de renderizado iniciales más rápidos y mejor rendimiento en tiempo de ejecución.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicaciones más ligeras:&lt;/strong&gt; Tamaños de paquete más pequeños y tiempos de carga de página más rápidos.&lt;/li&gt;
&lt;li&gt;**Depuración simplificada: **Rastros de pila más legibles que facilitan la identificación y resolución de errores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procesos de depuración más sencillos:&lt;/strong&gt; Elimina la complejidad asociada a ZoneJS, haciendo que la depuración sea más intuitiva.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La mejor forma de utilizar zoneless es con componentes que utilicen signals. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h1&amp;gt;Hello from {{ name() }}!&amp;lt;/h1&amp;gt;
    &amp;lt;button (click)="handleClick()"&amp;gt;Go Zoneless&amp;lt;/button&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Zoneless Angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo anterior, al hacer clic en el botón se invoca el método &lt;code&gt;handleClick&lt;/code&gt;, que actualiza el valor del signal y actualiza la interfaz de usuario. Esto funciona de manera similar a una aplicación que usa ZoneJS, con pocas diferencias. Con ZoneJS, Angular ejecutaba la detección de cambios cada vez que el estado de la aplicación podía haber cambiado. Sin zonas, Angular limita esta verificación a menos activadores, como actualizaciones de signals. Este cambio también incluye un nuevo programador con fusión para evitar verificar cambios varias veces consecutivas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Async/await nativo en aplicaciones zoneless
&lt;/h3&gt;

&lt;p&gt;ZoneJS tiene una particularidad: no puede funcionar con async/await. Quizás no lo sepas, pero cada vez que usas async/await en tu aplicación, la CLI transforma tu código para usar promesas "normales". Esto se llama reducción de nivel, ya que transforma el código ES2017 (async/await) en código ES2015 (promesas regulares).&lt;/p&gt;

&lt;p&gt;Hoy en día, si creas una aplicación que utiliza la detección de cambios sin ZoneJS (experimenta), Angular CLI utilizará el async/await nativo sin bajarlo a promesas. Esto mejorará la depuración y hará que tus paquetes sean más pequeños.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signals - Propuesta de Estandarización
&lt;/h2&gt;

&lt;p&gt;Esto no es exactamente nuevo en Angular v18, ya que en la version v17 se anuncio los nuevos signals inputs, signal queries y la nueva sintaxis de input y ouput.&lt;/p&gt;

&lt;p&gt;Ahora con la llegada de la de Angular v18 tenemos las Siganal APIs en &lt;code&gt;developer preview&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cada vez los signals se están volviendo mucho más populares, de hecho ya existe una propuesta para estandarizar los signals y que puedan ser agregados a JavaScript. Puedes profundizar en la &lt;a href="https://github.com/tc39" rel="noopener noreferrer"&gt;propuesta&lt;/a&gt; o en este interesante &lt;a href="https://eisenbergeffect.medium.com/a-tc39-proposal-for-signals-f0bedd37a335" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; para conocer más al respecto.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;new Signal.State()&lt;/code&gt; sería el equivalente de &lt;code&gt;signal()&lt;/code&gt; en Angular. &lt;code&gt;new Signal.Computed()&lt;/code&gt; sería el equivalente de &lt;code&gt;computed()&lt;/code&gt;. No hay equivalentes para el efecto: como todos los frameworks tienen necesidades ligeramente diferentes, esto queda fuera del alcance de la propuesta, y los frameworks pueden implementarlo como mejor les parezca basándose en el nuevo Signal.subtle.Watcher().&lt;/p&gt;

&lt;p&gt;Dato curioso: ¡El polyfill de Signal actual en la propuesta se basa en la implementación de Angular!&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in control flow - Ahora es estable
&lt;/h2&gt;

&lt;p&gt;La sintaxis de &lt;code&gt;Built-in control flow&lt;/code&gt; introducida en Angular v17 ya no es una función en &lt;code&gt;developer preview&lt;/code&gt; para desarrolladores y se puede utilizar de forma segura. Como ahora es la forma recomendada de escribir plantillas, debería considerar usarla en tus aplicaciones. Puede migrar fácilmente tus aplicaciones utilizando los esquemas proporcionados. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;ng&lt;/span&gt; generate @angular/core:control-flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Más información: &lt;a href="https://angular.dev/guide/templates/control-flow" rel="noopener noreferrer"&gt;Guía oficial&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferrable views - Ahora es estable
&lt;/h2&gt;

&lt;p&gt;La sintaxis &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; también es estable. &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; te permite definir un bloque de plantilla que se cargará de forma diferida cuando se cumpla una condición (con todos los componentes, canalizaciones, directivas y bibliotecas utilizadas en este bloque también cargados de forma diferida).&lt;/p&gt;

&lt;p&gt;Más información: &lt;a href="https://angular.dev/guide/defer" rel="noopener noreferrer"&gt;Guía oficial&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Material v3 - Ahora es estable
&lt;/h2&gt;

&lt;p&gt;Hace unos meses atras Angular introdujo suporte experimental para Material 3, ahora con la llegada de Angular v18 tenemos soporte estable, ahora podemos utilizar los nuevos features de Material 3 en nuestros prouyectos de Angular con Angular Material.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcita7ria7u44b96pxnj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcita7ria7u44b96pxnj0.png" alt="Angular Material home page" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mejoreas en el server-side rendering
&lt;/h2&gt;

&lt;p&gt;Con Angular v18 llegaron algunas nuevas características relacionas al Server Side Rendering (SSR).&lt;/p&gt;

&lt;h3&gt;
  
  
  Repetición de eventos
&lt;/h3&gt;

&lt;p&gt;Hace unos meses el equipo de Angular anuncion un proyecto en curso a largo plazo que tenia como objetivo fusionar Angualar y el framework interno llamado Google Wiz. Angular y Wiz han estado sirviendo a dos segmentos diferentes de aplicaciones en el pasado: Wiz se usó principalmente para aplicaciones centradas en el consumidor, muy centrada en el rendimiento y Angular se centró en la productividad y la experiencia del desarrollador.&lt;/p&gt;

&lt;p&gt;Como resultado de esta fusión Wiz integró profundamente Angular Signals en su modelo de renderizado. El equipo de Angular anunciuo que ahora Youtube usa Angular Signal, de la misma manera, Angular ahora ofrece cada vez más funciones centradas en el rendimiento, como la hidratación parcial, sobre las que compartiré más en un momento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6cwftouuu8z9c0gjbii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6cwftouuu8z9c0gjbii.png" alt="Angular and Wize" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora es posible registrar las interacciones del usuario durante la fase de hidratación y reproducirlas cuando la aplicación esté completamente cargada. Como sabrá, la fase de hidratación es la fase en la que el HTML renderizado por el servidor se transforma en una aplicación Angular completamente funcional, donde se agregan oyentes a los elementos existentes.&lt;/p&gt;

&lt;p&gt;Pero durante esta fase, el usuario puede interactuar con la aplicación, y estas interacciones se pierden (si el proceso de hidratación no es lo suficientemente rápido).&lt;/p&gt;

&lt;p&gt;Entonces, para algunas aplicaciones, puede resultar interesante registrar estas interacciones y reproducirlas cuando la aplicación esté completamente cargada.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ejemplo:
&lt;/h4&gt;

&lt;p&gt;Aunque la mayoría de los desarrolladores no trabajarán directamente con la reproducción de eventos, su utilidad es evidente. Imaginemos un sitio web de comercio electrónico con tiempos de carga lentos, como si tuviera una mala conexión. Un usuario intenta añadir varios productos al carrito mientras la página aún está cargando. Sin la reproducción de eventos, esas acciones se perderían.&lt;/p&gt;

&lt;p&gt;Con Angular v18, la reproducción de eventos entra en juego: el sistema registra las acciones del usuario incluso antes de que la página sea interactiva. Una vez que la página carga completamente, los eventos se reproducen, y los productos se añaden al carrito como si no hubiera habido ningún problema de carga.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8fe27qrvy8bxhqhjq6o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8fe27qrvy8bxhqhjq6o.gif" alt="Angular event replay example" width="1093" height="909"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La función de repetición de eventos está disponible en la versión 18 en &lt;code&gt;developer preview&lt;/code&gt;. Puedes habilitarlo usando &lt;code&gt;withEventReplay()&lt;/code&gt;, por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;bootstrapApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideClientHydration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;withEventReplay&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para que la reproducción de eventos funcione, Angular inyecta un pequeño script al principio de tu página HTML. Este script tiene la misión de "reproducir" las acciones del usuario que ocurrieron mientras la página aún se estaba cargando.&lt;/p&gt;

&lt;p&gt;¿Cómo lo hace? Primero, coloca un "oyente" en la raíz del documento que captura eventos específicos, como clics o doble clics, utilizando una técnica llamada delegación de eventos. Angular sabe qué eventos escuchar porque los recopiló durante el renderizado en el servidor.&lt;/p&gt;

&lt;p&gt;El resultado final es que cuando la página está completamente cargada, este script inteligente reproduce las acciones del usuario, activando las funciones correspondientes como si nada hubiera pasado. Aunque no todas las aplicaciones se beneficiarán de esta característica, sin duda es una herramienta poderosa para aquellos casos donde la interacción temprana del usuario es crucial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiencia de depuración mejorada
&lt;/h3&gt;

&lt;p&gt;Angular DevTools se ha actualizado para brindarte una mejor visión del proceso de hidratación. Ahora puedes ver el estado de hidratación de cada componente gracias a un nuevo ícono junto a su nombre. Y si quieres una vista general, activa el modo de superposición para ver al instante qué componentes ya están hidratados en la página. ¿Lo mejor? Si tu aplicación tiene errores de hidratación, Angular DevTools te los mostrará directamente en el explorador de componentes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9967dtx0kdr9dx16q1pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9967dtx0kdr9dx16q1pv.png" alt="Angular DevTools Hydration debugging" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Soporte para Hidratación en CDK y Material
&lt;/h3&gt;

&lt;p&gt;En la versión 17, algunos componentes de Angular Material y CDK optaron por no hidratarse, lo que provocó su repetición. A partir de la versión 18, todos los componentes y primitivas son totalmente compatibles con la hidratación.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hidratación parcial
&lt;/h3&gt;

&lt;p&gt;El equipo de Angular anuncio durante el Google I/O la hidratación parcial que es una técnica que te permite hidratar tu aplicación de forma incremental después del renderizado del lado del servidor. La hidratación incremental de tu aplicación permite cargar menos JavaScript por adelantado y mejora el rendimiento.&lt;/p&gt;

&lt;p&gt;Imagina que puedes cargar tu aplicación web por partes, como si fuera un rompecabezas, empezando por las piezas más importantes. Eso es precisamente lo que permite la hidratación incremental: en lugar de cargar todo el código JavaScript de golpe, solo se carga lo esencial para mostrar la página rápidamente. El resto se va añadiendo sobre la marcha, mejorando significativamente el rendimiento.&lt;/p&gt;

&lt;p&gt;La hidratación parcial lleva esta idea un paso más allá. Basándose en el concepto de "vistas diferibles", permite renderizar en el servidor el contenido principal de una sección específica de la página (marcada con &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt;). Luego, en el navegador del usuario, Angular carga el código JavaScript asociado y "hidrata" esa sección solo cuando se cumplen ciertas condiciones, como por ejemplo, cuando el usuario interactúa con ella. De esta forma, se reduce la cantidad inicial de JavaScript y la página se vuelve más rápida e interactiva. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El bloque de arriba representará el componente de calendario en el servidor. Una vez que llegue al cliente, Angular descargará el JavaScript correspondiente e hidratará el calendario haciéndolo interactivo solo después de que ingrese a la ventana gráfica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firebase App Hosting
&lt;/h3&gt;

&lt;p&gt;Firebase presentó en Google I/O su nuevo servicio de App Hosting, diseñado para simplificar al máximo la creación y publicación de aplicaciones web dinámicas.&lt;/p&gt;

&lt;p&gt;¿Qué lo hace tan especial? App Hosting se integra a la perfección con el ecosistema de Firebase, ofreciendo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Soporte nativo para Angular:&lt;/strong&gt; Configuración y despliegue sin complicaciones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integración con GitHub:&lt;/strong&gt; Facilita el flujo de trabajo desde el desarrollo hasta la producción.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conexión directa con otros servicios de Firebase:&lt;/strong&gt; Aprovecha al máximo Authentication, Cloud Firestore, Vertex AI y más, sin configuraciones complejas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con App Hosting, Firebase se convierte en una solución aún más completa para construir y escalar aplicaciones Angular de forma rápida y segura. Dale un vistazo a la &lt;a href="https://firebase.google.com/docs/app-hosting/get-started" rel="noopener noreferrer"&gt;guía&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuevo paquete de construcción
&lt;/h2&gt;

&lt;p&gt;Angular está simplificando su sistema de construcción de proyectos. Para ello, han creado un nuevo paquete llamado &lt;code&gt;@angular/build&lt;/code&gt;, que se centra en las herramientas modernas como esbuild y Vite.&lt;/p&gt;

&lt;p&gt;Antes, todas las herramientas de construcción, incluyendo Webpack, estaban juntas en @angular-devkit/build-angular. Al separar esbuild y Vite en su propio paquete, &lt;code&gt;@angular/build&lt;/code&gt; se vuelve más ligero y eficiente.&lt;/p&gt;

&lt;p&gt;Si actualizas tu proyecto a Angular v18, tendrás la opción de migrar a este nuevo sistema. La migración actualizará tu archivo angular.json para que use &lt;code&gt;@angular/build&lt;/code&gt; en lugar de &lt;code&gt;@angular-devkit/build-angular&lt;/code&gt; y ajustará las dependencias en tu package.json.&lt;/p&gt;

&lt;p&gt;Pero no te preocupes, esta migración solo se realizará si no utilizas Webpack en tu proyecto. Si tus pruebas se basan en Karma, que a su vez usa Webpack, no se hará ningún cambio. En resumen, Angular te ofrece un camino más limpio y moderno para construir tus aplicaciones, sin afectar proyectos que aún dependen de Webpack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redirecciones de ruta como funciones
&lt;/h2&gt;

&lt;p&gt;Angular ahora te da más control sobre las redirecciones en tus aplicaciones. Antes, solo podías redirigir a una ruta fija, sin importar el contexto. ¡Pero eso ha cambiado!&lt;/p&gt;

&lt;p&gt;Con Angular v18, la propiedad &lt;code&gt;redirectTo&lt;/code&gt; de una ruta ahora acepta una función, llamada &lt;code&gt;RedirectFunction&lt;/code&gt;, que te permite crear redirecciones dinámicas y mucho más inteligentes.&lt;/p&gt;

&lt;p&gt;¿Cómo funciona? La &lt;code&gt;RedirectFunction&lt;/code&gt; recibe información sobre la ruta actual, como parámetros o consultas, y en base a eso, decide a dónde redirigir al usuario. Además, puedes usar servicios dentro de esta función, lo que abre un abanico de posibilidades para crear reglas de redirección sofisticadas. Esta función también es similar a las guardias y se ejecuta en el inyector de entorno: esto significa que puede inyectar servicios si es necesario. La función puede devolver una cadena o un &lt;code&gt;UrlTree&lt;/code&gt;. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ErrorHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userIdParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userIdParam&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`/user/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userIdParam&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;errorHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Se intentó navegar a la página del usuario sin ID de usuario.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`/not-found`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user/:userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OtherComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  HttpClientModule - Depreación
&lt;/h2&gt;

&lt;p&gt;Angular sigue avanzando hacia un futuro donde los componentes independientes (Standolone components) son la norma, y esto significa que algunos módulos tradicionales están empezando a ser reemplazados. &lt;/p&gt;

&lt;p&gt;En Angular v18, los módulos &lt;code&gt;HttpClientModule&lt;/code&gt; (junto con &lt;code&gt;HttpClientTestingModule&lt;/code&gt;, &lt;code&gt;HttpClientXsrfModule&lt;/code&gt;, y &lt;code&gt;HttpClientJsonpModule&lt;/code&gt;) han sido marcados como obsoletos.  Esto no significa que ya no funcionen, pero sí que es hora de empezar a usar alternativas más modernas.&lt;/p&gt;

&lt;p&gt;En su lugar, ahora puedes utilizar las funciones &lt;code&gt;provideHttpClient()&lt;/code&gt; (con opciones para XSRF o JSONP) y &lt;code&gt;provideHttpClientTesting()&lt;/code&gt;.  Estas funciones ofrecen una forma más directa y eficiente de configurar el cliente HTTP en tus aplicaciones.&lt;/p&gt;

&lt;p&gt;Y como siempre, el equipo de Angular ha pensado en todo.  Al actualizar tu proyecto con &lt;code&gt;ng update @angular/core&lt;/code&gt;,  se te preguntará si quieres migrar automáticamente tus módulos HTTP a la nueva sintaxis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contenido alternativo para ng-content
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ng-content&amp;gt;&lt;/code&gt; es una característica poderosa en Angular, pero tiene una limitación: no puede tener contenido alternativo. ¡Este ya no es el caso en Angular v18!&lt;/p&gt;

&lt;p&gt;Ahora podemos agregar algo de contenido dentro de la etiqueta &lt;code&gt;&amp;lt;ng-content&amp;gt;&lt;/code&gt;, y este contenido se mostrará si no se proyecta ningún contenido en el componente.&lt;/p&gt;

&lt;p&gt;Sólo necesitas poner el contenido alternativo dentro de la etiqueta &lt;code&gt;ng-content&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;ng-content select="header"&amp;gt; Default header &amp;lt;/ng-content&amp;gt;

    &amp;lt;ng-content&amp;gt; Default main content &amp;lt;/ng-content&amp;gt;

    &amp;lt;ng-content select="footer"&amp;gt; Default footer &amp;lt;/ng-content&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como puedes ver, esta nueva característica te permite definir fácilmente un contenido alternativo dedicado para cada elemento &lt;code&gt;ng-content&lt;/code&gt; en tu componente.&lt;/p&gt;

&lt;p&gt;Entonces, considerando el siguiente ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;footer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/footer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/my-component&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Default&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;

&lt;span class="nx"&gt;Default&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;footer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/footer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nota: antes de Angular v18, esto provocaría un error.&lt;/p&gt;

&lt;h2&gt;
  
  
  angular.dev - La nueva documentación oficial de Angular
&lt;/h2&gt;

&lt;p&gt;El equipo de Angular ha anunciado que ahora angular.dev es el nuevo sitio web oficial de la documentación.&lt;/p&gt;

&lt;p&gt;Angular v18 llega cargado de mejoras que hacen del desarrollo web una experiencia más fluida, eficiente y satisfactoria. Desde la optimización del rendimiento hasta la inclusión de nuevas funcionalidades, esta versión nos equipa con las herramientas necesarias para construir aplicaciones web de última generación. ¡No hay tiempo que perder, es hora de actualizar nuestros proyectos y sumergirnos en las posibilidades que nos ofrece Angular v18!&lt;/p&gt;

&lt;p&gt;Muchas gracias por leerme, Espero que este recorrido por las novedades de Angular v18 te haya resultado útil. &lt;/p&gt;

&lt;p&gt;Si te ha gustado el artículo, ¡compártelo en tus redes sociales!&lt;/p&gt;

&lt;p&gt;Sígueme en Twitter/X &lt;a href="https://twitter.com/ricardo_chl" rel="noopener noreferrer"&gt;ricardo_chl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Omitir un Interceptor de Angular usando Context para Http Interceptors</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Mon, 01 Nov 2021 16:21:18 +0000</pubDate>
      <link>https://forem.com/ricardochl/omitir-un-interceptor-de-angular-usando-context-para-http-interceptors-cf0</link>
      <guid>https://forem.com/ricardochl/omitir-un-interceptor-de-angular-usando-context-para-http-interceptors-cf0</guid>
      <description>&lt;p&gt;Los interceptors en Angular llegaron desde la versión 4.3 y básicamente nos brindan un mecanismo para interceptar y/o mutar las solicitudes y respuestas http. Más detalles &lt;a href="https://dev.to/ricardochl/como-usar-httpinterceptors-en-angular-2o84"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Los interceptors en Angular interceptan todas las peticiones http por defecto, pero hay ocasiones en donde deseamos omitir un interceptor para algunas solicitudes.&lt;/p&gt;

&lt;p&gt;Antes de la versión 12 de Angular era muy común hacer esto de alguna de las siguientes formas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agregar encabezados http en la solicitud http y luego evaluar ese encabezado en el interceptor.&lt;/li&gt;
&lt;li&gt;Crear un nuevo httpClient para esa solicitud.&lt;/li&gt;
&lt;li&gt;Administrar sus inyecciones de HttpClient con tokens.&lt;/li&gt;
&lt;li&gt;Utilizar httpBackend y saltarse todos los interceptors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  HttpContext
&lt;/h2&gt;

&lt;p&gt;Desde la versión 12 de Angular tenemos una mejor forma de hacer esto, la cual consiste en pasar metadatos a los interceptors http. Ya podemos olvidarnos de pasar encabezados personalizados a nuestros interceptors.&lt;/p&gt;

&lt;p&gt;Un caso de uso común es indicarle al interpcetor que la solicitud http actual es anónima y no necesita un JWT (JSON WEB TOKEN).&lt;/p&gt;

&lt;p&gt;Otro caso también podría ser  indicarle al interceptor que una solicitud se puede almacenar en caché.&lt;/p&gt;

&lt;p&gt;Nota: Recuerda que tenemos que tener la Angular v12 o superior en nuestro proyecto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HttpContext:&lt;/strong&gt; El contexto HTTP almacena valores arbitrarios definidos por el usuario y garantiza la seguridad de los tipos sin conocer realmente los tipos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context:&lt;/strong&gt; Es mutable y se comparte entre solicitudes clonadas a menos que se especifique explícitamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;//token.interpcetor.ts&lt;/span&gt;

&lt;span class="c1"&gt;//Declaramos un nuevo HttpContextToken&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BYPASS_JW_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpContextToken&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TokenInterceptor&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//Aquí evaluamos el contexto y omitimos el interceptor.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BYPASS_JW_TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// service&lt;/span&gt;

&lt;span class="cm"&gt;/*
Así se ve una solicitud en la cual se quiere omitir el JWT, 
debemos pasar un nuevo contexto con el HttpContextToken 
declarado anteriormente en el interceptor.
*/&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/fakeEndPoint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpContext&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BYPASS_JW_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Más detalles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El token pasado al contexto del http interceptor puede ser cualquier tipo de dato como ser booleano, número, cadena, objeto etc.
-El token pasado al contexto no debe confundirse con el JWT el cual es requerido para algunas solicitudes http.&lt;/li&gt;
&lt;li&gt;La declaración del HttpContextToken se puede realizar donde tenga más sentido, aunque lo común es declararlo en el interceptor que lo va a utilizar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Muchas gracias por leer este post.&lt;/p&gt;

&lt;p&gt;Sígueme en twitter &lt;a href="https://twitter.com/ricardo_chl" rel="noopener noreferrer"&gt;ricardo_chl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Novedades de Angular v12</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Thu, 13 May 2021 18:53:22 +0000</pubDate>
      <link>https://forem.com/ricardochl/novedades-de-angular-v12-1j3n</link>
      <guid>https://forem.com/ricardochl/novedades-de-angular-v12-1j3n</guid>
      <description>&lt;p&gt;El 12 de mayo del 2021, se lanzo el release de Angular v12.&lt;/p&gt;

&lt;p&gt;En este post quiero compartir algunas de las novedades de esta versión.&lt;/p&gt;

&lt;p&gt;Empecemos...&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrando a Ivy por completo
&lt;/h2&gt;

&lt;p&gt;La nueva evolución de Angular que llego con Ivy ahora se esta completando, el equipo se esta moviendo por completo a Ivy.&lt;/p&gt;

&lt;p&gt;Al antiguo view engine de Angular ha quedado obsoleto y se eliminará en una versión futura. &lt;/p&gt;

&lt;p&gt;Aunque view engine está obsoleto, existen algunas librerías que lo utilizan y que seguirán funcionando con Ivy. (No se requiere que los desarrolladores hagan algún cambio especifico para obtener este soporte), pero los autores de las librerías deben preocuparse por realizar la transición a Ivy.&lt;/p&gt;

&lt;h2&gt;
  
  
  ID de mensajes de i18n
&lt;/h2&gt;

&lt;p&gt;Actualmente, hay varios formatos de identificación de mensajes que son legacy los cuales se utilizan en el sistema i18n. Con estos identificadores pueden surgir algunos problemas (con los espacios en blanco por ejemplo). Para resolver esos problemas el equipo de Angular esta migrando por completo a los nuevos ID de mensajes. El nuevo formato de identificación de mensajes es mucho más intuitivo.&lt;/p&gt;

&lt;p&gt;Desde v11, los nuevos proyectos se configuran automáticamente para usar los nuevos ID de mensajes. &lt;a href="https://angular.io/guide/migration-legacy-message-id" rel="noopener noreferrer"&gt;aquí&lt;/a&gt; una guía para la migración de legacy ids al nuevo formato.&lt;/p&gt;

&lt;h2&gt;
  
  
  El futuro de Protactor
&lt;/h2&gt;

&lt;p&gt;El equipo de Angular ha optado por no incluir Protactor en nuevos proyectos, y está brindando soluciones de terceros que son bastante populares como Cypress, esto para ayudar a que los desarrolladores tengan soluciones alternativas.&lt;/p&gt;

&lt;p&gt;También el equipo ha estado en constante trabajo con la comunidad para escuchar sus comentarios sobre Protactor y en base a eso poder tomar una decisión en el futuro.&lt;/p&gt;

&lt;p&gt;Más información &lt;a href="https://github.com/angular/protractor/issues/5502" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operador null-coalescing (??)
&lt;/h2&gt;

&lt;p&gt;El operador null-coalescing (??) ha permitido a los desarrolladores escribir un código mas limpio y práctico en TypeScript. Ahora con el release de Angular v12 tenemos soporte para utilizar este operador en las plantillas de los componentes.&lt;/p&gt;

&lt;p&gt;Entonces, eso quiere decir que si tenemos una sintaxis como la siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;impuesto&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;impuesto&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;impuesto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;calcularImpuesto&lt;/span&gt;&lt;span class="p"&gt;()}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se convierte en lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;impuesto&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nf"&gt;calcularImpuesto&lt;/span&gt;&lt;span class="p"&gt;()}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mejoras en la documentación
&lt;/h2&gt;

&lt;p&gt;Siempre hay mucha gente queriendo aprender Angular y no sabe por donde iniciar, el equipo de Angular ha identificado algunas oportunidades de mejora y ha realizado un gran esfuerzo por mejorar documentación oficial &lt;a href="//angular.io"&gt;angular.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Han escrito varias guías para los que vienen iniciando con el framework, esto está en un apartado llamado "Understanding Angular", si bien estas guías no son nuevas, el equipo ha estado en constante mejora de este contenido y agregando cada vez más, tal es el caso de la guía &lt;a href="https://angular.io/guide/content-projection" rel="noopener noreferrer"&gt;Content projection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;También se actualizo la &lt;a href="https://angular.io/guide/contributors-guide-overview" rel="noopener noreferrer"&gt;guía para contribuciones&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sass en línea
&lt;/h2&gt;

&lt;p&gt;A partir de la v12, los componentes de Angular ahora admitirán Sass en línea en el campo &lt;strong&gt;styles&lt;/strong&gt; del decorador &lt;strong&gt;@component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Anteriormente, Sass solo estaba disponible en recursos externos debido al compilador Angular. Para activar esta función en las aplicaciones existentes tenemos que añadir "inlineStyleLanguage": "scss”a angular.json. De lo contrario, estará disponible para nuevos proyectos que utilicen SCSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular CDK y Angular Material
&lt;/h2&gt;

&lt;p&gt;Angular CDK y Angular Material han adoptado internamente el nuevo sistema de módulos de Sass. Los desarrolladores deben asegurarse de cambiar el paquete "node-sass" al paquete "sass".&lt;/p&gt;

&lt;p&gt;El node-sass ya no esta al día con la nuevas funciones de sass.&lt;/p&gt;

&lt;p&gt;Ademas, ambos (Angular CDK y Angular Material) exponen una nueva API diseñada para se consumida con la nueva sintaxis &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/use"&gt;@use&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cuando se actualiza una aplicación a la v12, la app cambiara automáticamente a la nueva API de sass.&lt;/p&gt;

&lt;p&gt;Visita la documentación oficial de &lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;Angular Material&lt;/a&gt; para obtener mas información.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soporte de Webpack 5 en produción
&lt;/h2&gt;

&lt;p&gt;En la v11 se agrego soporte experimental para Webpack 5, ahora con la v12 tenemos soporte de Webpack 5 para su uso en producción.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modo producción y modo estricto por defecto, TypeScript 4.2
&lt;/h2&gt;

&lt;p&gt;La ejecución ng build ahora tiene como valor predeterminado &lt;strong&gt;producción&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;El modo estricto está habilitado de forma predeterminada en la CLI.&lt;/p&gt;

&lt;p&gt;Angular v12 es compatible con TypeScript 4.2&lt;/p&gt;

&lt;h2&gt;
  
  
  Desactivación del soporte para IE11
&lt;/h2&gt;

&lt;p&gt;El equipo esta enfocado en brindar soluciones modernas para el framework, eliminar el soporte de esta compatibilidad permite que se puedan enfocar en otras soluciones  y brindar una mejor experiencias a los usuarios y desarrolladores.&lt;/p&gt;

&lt;p&gt;Angular v12 incluye un nuevo mensaje de advertencia en navegadores IE11, este soporte de eliminará por completo en Angular v13.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actualizar a la v12
&lt;/h2&gt;

&lt;p&gt;Angular nos brinda un comando para actualizar nuestras aplicaciones de una manera sencilla el cual es &lt;strong&gt;ng update&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Si tenemos aplicaciones un poco mas complejas podemos seguir la guía para actualizar, la pueden encontrar &lt;a href="https://update.angular.io/" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusiones
&lt;/h3&gt;

&lt;p&gt;Me alegra mucho que el equipo de Angular ahora este mas conectado con la comunidad, escuchando sus comentarios y trabajando en conjunto.&lt;/p&gt;

&lt;p&gt;Angular v12 llego con muchas características importantes que sin duda nos ayudaran a mejorar nuestra experiencia como desarrolladores, y a su vez la de los usuarios.&lt;/p&gt;

&lt;p&gt;Gracias por leer está publicación.&lt;/p&gt;

</description>
      <category>angular</category>
    </item>
    <item>
      <title>¿Cómo servir archivos estáticos en Express?</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Mon, 03 May 2021 04:02:51 +0000</pubDate>
      <link>https://forem.com/ricardochl/como-servir-archivos-estaticos-en-express-271k</link>
      <guid>https://forem.com/ricardochl/como-servir-archivos-estaticos-en-express-271k</guid>
      <description>&lt;p&gt;En este pequeño articulo aprenderás como servir archivos estáticos en Express.&lt;/p&gt;

&lt;p&gt;Express es framework de Node Js el cual nos permite crear API's y servicios web robustos de una manera más fácil.&lt;/p&gt;

&lt;p&gt;Si tenemos nuestra API desarrollada con Express sera muy fácil agregarle la capacidad de que pueda manejar los archivos estáticos.&lt;/p&gt;

&lt;p&gt;Llámese archivos estáticos a imágenes, videos, archivos de audio, documentos en distintos formatos, fuentes, archivos de JavaScript, html y css, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iniciemos
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Configuración de Express
&lt;/h2&gt;

&lt;p&gt;Primero vamos a crear un proyecto para de Node para este ejemplo, en este caso voy a inicializar todos los valores predeterminados utilizando la bandera "-y", esto configurará un archivo package.json para manejar las dependencias.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;npm&lt;/span&gt; &lt;span class="err"&gt;init&lt;/span&gt; &lt;span class="err"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora creamos un archivo de entrada con el nombre index.js, aquí es donde crearemos el servidor de Express.&lt;/p&gt;

&lt;p&gt;Bien, ahora instalemos express como dependencia de nuestro proyecto&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;npm&lt;/span&gt; &lt;span class="err"&gt;install&lt;/span&gt; &lt;span class="err"&gt;express&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En nuestro package.json agreguemos un comando que nos permitirá iniciar el servidor que crearemos en breve.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;  &lt;span class="err"&gt;"start":&lt;/span&gt; &lt;span class="err"&gt;"node&lt;/span&gt; &lt;span class="err"&gt;index.js"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El package.json deberá verse así&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-static-files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keywords&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ricardo Chavarria&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;license&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ISC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^4.17.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Carpeta de archivos estáticos
&lt;/h2&gt;

&lt;p&gt;Para almacenar los archivos estáticos, creemos una carpeta llamada "public" en la raíz de nuestro proyecto, y podemos agregar algunos archivos en mi caso colocare una imagen y un archivo html.&lt;/p&gt;

&lt;p&gt;La estructura de archivos se vera así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmefj2x42mnu6yfwe71p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmefj2x42mnu6yfwe71p.png" alt="image" width="486" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creación del servidor con Express
&lt;/h2&gt;

&lt;p&gt;En el index.js, vamos requerir express y hacemos una instancia del mismo, luego implementamos una solicitud get y finalmente levantamos nuestro servidor para que funcione en el puerto 3000.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server listening on port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejecutamos "npm run start" en la terminal y veremos el siguiente mensaje.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;Server&lt;/span&gt; &lt;span class="err"&gt;listening&lt;/span&gt; &lt;span class="err"&gt;on&lt;/span&gt; &lt;span class="py"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y sí accedemos en nuestro navegador a &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt; debemos de ver el mensaje de 'Hello World!' que implementamos en la solicitud get. &lt;/p&gt;

&lt;p&gt;Bien hecho, ya tenemos nuestro servidor de Express configurado correctamente, solo queda agregarle la capacidad a nuestro servidor de que pueda manejar archivos estáticos.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Sirviendo Archivos Estáticos
&lt;/h2&gt;

&lt;p&gt;Utilizaremos el módulo path de Node Js, este modulo contiene todas las utilidades para trabajar con rutas de archivos. No necesitamos instalar nada, solo es necesario requerirlo en nuestro archivo index.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora sí, con la siguiente linea de código le decimos a express que pueda servir archivos estáticos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando usamos app.use(), le estamos diciendo a Express que use un Middleware, el Middleware básicamente es un bloque de código o función que se ejecuta entre la petición que hace el usuario hasta que la petición llega al servidor, funciona como una especie de proxy.&lt;/p&gt;

&lt;p&gt;express.static() busca  y devuelve los archivos estáticos solicitados por el usuario y recibe como parámetro la ruta del folder donde están esos archivos.&lt;/p&gt;

&lt;p&gt;Utilizamos el modulo path para proporcionar una ruta absoluta de la carpeta, ya que se colocas la ruta directamente estarías proporcionando una ruta relativa y si ejecutas la aplicación desde otro directorio o similar puedes tener problemas, por ello se recomienda utilizar la ruta absoluta y módulo path nos ayuda con eso.&lt;/p&gt;

&lt;p&gt;El index.js se veria así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server listening on port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Probando la aplicación
&lt;/h2&gt;

&lt;p&gt;Creemos un archivo index.html en la carpeta public, agreguemos lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"IE=edge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Archivos Estáticos&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Sirviendo archivos estáticos en Express&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora ejecutemos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;npm&lt;/span&gt; &lt;span class="err"&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vayamos a &lt;a href="http://localhost:3000/public/" rel="noopener noreferrer"&gt;http://localhost:3000/public/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deberíamos de ver lo siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmanvytcnufvts1dci2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmanvytcnufvts1dci2a.png" alt="image" width="570" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;También podemos servir imágenes &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekfzcsqm7zzo6eob4xyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekfzcsqm7zzo6eob4xyj.png" alt="image" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esto hemos finalizado.&lt;/p&gt;

&lt;p&gt;El repositorio de este tutorial lo puedes encontrar &lt;a href="https://github.com/ricardochl/express-static-files" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Déjame saber en los comentarios que te pareció este tutorial.&lt;/p&gt;

&lt;p&gt;Gracias por leer está publicación.&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Login con Angular y Auth0</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Thu, 29 Apr 2021 19:45:27 +0000</pubDate>
      <link>https://forem.com/ricardochl/angular-login-with-auth0-4d8l</link>
      <guid>https://forem.com/ricardochl/angular-login-with-auth0-4d8l</guid>
      <description>&lt;p&gt;Auth0 es una solución flexible e integrada para agregar servicios de autenticación y autorización a sus aplicaciones.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;¿Por qué usar Auth0?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Como mencione anteriormente desarrollar un sistema de autenticación desde cero puede ser bastante complejo. Auth0 es una plataforma de identidad como servicio (IDaaS) que permite centralizar y autenticación y autorización aplicaciones y brindar un sistema de seguridad seguro para sus usuarios y de esta manera reduciendo la complejidad para la seguridad de sus aplicaciones.&lt;/p&gt;

&lt;p&gt;Auth0 brinda funciones de seguridad listas para ser usada en sus apps, con Auth0 podrá integrar en sus app inicio de sesión con correo electrónico y contraseña e inicio de sesión social con terceros como (Google, Facebook, Github, etc)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contenido&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear Aplicación de Angular&lt;/li&gt;
&lt;li&gt;Configurar Angular App en Auth0.com&lt;/li&gt;
&lt;li&gt;Configuración del Auth0 Angular SDK&lt;/li&gt;
&lt;li&gt;Autenticar usuario&lt;/li&gt;
&lt;li&gt;Recuperar perfil del usuario&lt;/li&gt;
&lt;li&gt;Proteger rutas&lt;/li&gt;
&lt;li&gt;Conclusión&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Iniciemos&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Crear Aplicación de Angular&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lo primero que debemos hacer es crear la aplicación sobre la cual vamos a trabajar, ejecutamos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;new&lt;/span&gt; &lt;span class="err"&gt;angular-login-auth0&lt;/span&gt; &lt;span class="err"&gt;--routing&lt;/span&gt; &lt;span class="py"&gt;--style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;scss&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez creada la app accedemos al directorio&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;cd&lt;/span&gt; &lt;span class="err"&gt;angular-login-auth0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Configurar Angular App en Auth0.com&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Antes de iniciar a integrar el SDK de Auth0 para Angular, tenemos que crear una cuenta en auth0.com y registrar un aplicación de tipo SPA.&lt;/p&gt;

&lt;p&gt;Vamos a ir a &lt;a href="https://auth0.com" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt; puede ir a la opción de "Sign Up" y crear un cuenta , es super sencillo, también puede iniciar con acceso social con Google o Github.&lt;/p&gt;

&lt;p&gt;Auth0 te solicitara la creación de un &lt;strong&gt;Auth0 Tenant&lt;/strong&gt; que no es mas que un contenedor que utiliza Auth0 para para almacenar su configuración de servicio de identidad y sus usuarios de forma aislada.&lt;/p&gt;

&lt;p&gt;Ningún otro usuario de Auth0 puede ver el tenant que haz creado ni tu puedes ver el de otros usuarios.&lt;/p&gt;

&lt;p&gt;Una vez que ha configurado lo anterior, Auth0 lo lleva al panel de administración donde se podrán administrar y configurar todos los servicios de Auth0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnubhccotoc5hs1kfoz58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnubhccotoc5hs1kfoz58.png" alt="Alt Text" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Crear Aplicación en Auth0&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Tenemos que crear una aplicación en Auth0 la cual vamos a conectar con nuestra app de Angular que hemos creado previamente.&lt;/p&gt;

&lt;p&gt;En el menu lateral izquierdo vamos, hacemos clic en la opción aplicaciones y luego en crear aplicación.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yamzuqus6qwncoz4ckh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yamzuqus6qwncoz4ckh.png" alt="image" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para este ejemplo nombre la app como "Angular Login", se debe elegir la opción de Single Page Web Applications ya que estamos trabajando en una SPA con Angular.&lt;/p&gt;

&lt;p&gt;Una vez crear la aplicación haga clic en la tab de &lt;strong&gt;settings&lt;/strong&gt; aquí es donde esta toda la configuración de su aplicación especifica, incluyendo su ClientId y Client Secret.&lt;/p&gt;

&lt;h4&gt;
  
  
  Comunicación entre Angular y Auth0
&lt;/h4&gt;

&lt;p&gt;Cuando se trabaja con Auth0, no es necesario que nosotros creemos un formulario de inicio de sesión, Auth0 ya ofrece una página de acceso universal. Este formulario reduce el riesgos a nivel de seguridad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwx4r1xm6v0j3nk1ha3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwx4r1xm6v0j3nk1ha3b.png" alt="image" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Cómo funciona el acceso universal?
&lt;/h4&gt;

&lt;p&gt;Cuando un usuario intente iniciar sesión en la aplicación de Angular se redirigirá a Auth0 y les mostrar la página de inicio de sesión universal. Para que esa redirección se realice de forma segura, debe especificar en la configuración de la aplicación Auth0 las URL a las que Auth0 puede redirigir a los usuarios una vez que los autentica.&lt;/p&gt;

&lt;p&gt;Primero configuremos a donde debe ser redirigido el usuario cuando haya iniciado sesión de manera correcta&lt;/p&gt;

&lt;p&gt;En la opción "Allowed Callback URLs" colocamos lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;//localhost:4200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego hay que configurar también a dónde debe ser redirigido el usuario cuando haya cerrado la sesión de manera correcta.&lt;/p&gt;

&lt;p&gt;En la opción "Allowed Logout URLs" colocamos lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;//localhost:4200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth0 solo podrá redirigir al usuario a las URL que haya colocado anteriormente como origenes permitidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Orígenes web permitidos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando se utiliza el Auth0 Angular SDK, la aplicación de Angular realiza solicitudes bajo el capó a la API de Auth0, esto para manejar las solicitudes de autenticación, es por ello que debe agregar la URL de origen de su aplicación angular para evitar problemas de intercambio de recursos de origen cruzado (CORS).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;//localhost:4200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para finalizar hacemos clic en "Guardar Cambios".&lt;/p&gt;

&lt;h4&gt;
  
  
  Variables de configuración
&lt;/h4&gt;

&lt;p&gt;Para permitir que la Aplicación de Angular se comunique con Auth0 se necesitan los valores de ID de cliente y dominio Auth0. Estos valores están en la "pestaña" de settings&lt;/p&gt;

&lt;p&gt;En su aplicación de Angular cree un archivo llamado auth_config.json (A nivel del proyecto)&lt;/p&gt;

&lt;p&gt;Este archivo debe contener la siguiente información&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;"domain":&lt;/span&gt; &lt;span class="err"&gt;"YOUR_AUTH0_DOMAIN",&lt;/span&gt;
  &lt;span class="err"&gt;"clientId":&lt;/span&gt; &lt;span class="err"&gt;"YOUR_AUTH0_CLIENT_ID"&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estas variables permiten que su aplicación Angular se identifique como una parte autorizada para interactuar con el servidor de autenticación Auth0 para llevar a cabo el proceso de autenticación.&lt;/p&gt;

&lt;p&gt;Ahora debemos usar estas variables en la aplicación Angular para eso vamos a utilizar el environment de Angular.&lt;/p&gt;

&lt;p&gt;El environment debería verse así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../auth_config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redirectUri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para poder importar archivos JSON dentro de Angular, tenemos que establecer "resolveJsonModule": true en nuestro tsconfig.json&lt;/p&gt;

&lt;p&gt;Con estos pasos realizados se ha completado la configuración de un servicio de autenticación que esta listo para ser consumido por la aplicación de Angular&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Configuración del Auth0 Angular SDK&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ejecute el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;@auth0/auth0-angular&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El nuevo Auth0 Angular SDK brinda varios métodos, variables y tipos que ayudan a integrar Auth0 con una aplicación de Angular de una manera más sencilla, este SDK incluye un módulo de autenticación y un servicio.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementar módulo de autenticación
&lt;/h4&gt;

&lt;p&gt;Importar AuthModule y environment en el AppModule y luego inicializarlo en los imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppRoutingModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app-routing.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../environments/environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppComponent&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AppRoutingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AuthModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;4. Autenticar usuario&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Auth0 Angular SDK proporciona métodos para activar eventos de autenticación dentro de los componentes Angular: inicio de sesión, cierre de sesión y registro etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creando componentes
&lt;/h4&gt;

&lt;p&gt;Vamos a necesitar algunos componentes de Angular para permitirle a usuario iniciar y cerrar la sesión&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pagina de inicio&lt;/li&gt;
&lt;li&gt;Botón para iniciar sesión&lt;/li&gt;
&lt;li&gt;Botón para cerrar la sesión&lt;/li&gt;
&lt;li&gt;Component para manejar que Botón mostrar si el de inicio o cierre de sesión.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Con los siguientes comando los podemos crear&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;g&lt;/span&gt; &lt;span class="err"&gt;c&lt;/span&gt; &lt;span class="err"&gt;pages/home&lt;/span&gt;
&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;g&lt;/span&gt; &lt;span class="err"&gt;c&lt;/span&gt; &lt;span class="err"&gt;components/login-button&lt;/span&gt;
&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;g&lt;/span&gt; &lt;span class="err"&gt;c&lt;/span&gt; &lt;span class="err"&gt;components/logout-button&lt;/span&gt;
&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;g&lt;/span&gt; &lt;span class="err"&gt;c&lt;/span&gt; &lt;span class="err"&gt;components/authentication-button&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El component home únicamente lo utilizaremos para mostrar  los botones según sea el caso &lt;/p&gt;

&lt;p&gt;Nuestro archivo de rutas debería verse así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/home/home.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppRoutingModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora el login-button.component.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-login-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./login-button.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./login-button.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginButtonComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;loginWithRedirect&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loginWithRedirect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y el html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"loginWithRedirect()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Log in
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora seguimos con el botón para cerrar la sesión&lt;/p&gt;

&lt;p&gt;logout-button.component.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DOCUMENT&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-logout-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./logout-button.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./logout-button.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogoutButtonComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DOCUMENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;returnTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y el html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"logout()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Log out
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se agrega la propiedad &lt;strong&gt;returnTo&lt;/strong&gt; al objeto de configuración para especificar la URL a la que Auth0 debe redirigir a sus usuarios después de cerrar la sesión. En este momento, está trabajando localmente y las "URL de cierre de sesión permitidas" de su aplicación Auth0 apuntan a &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt;, estas url las configuramos previamente.&lt;/p&gt;

&lt;p&gt;Sin embargo, si tuviera que implementar su aplicación Angular en producción , debe agregar la URL de cierre de sesión de producción a la lista "URL de cierre de sesión permitidas.&lt;/p&gt;

&lt;p&gt;Otro punto importante es que los componentes de Angular no tiene acceso al objeto &lt;strong&gt;document&lt;/strong&gt;, pero se puede inyectar con el @Inject(DOCUMENT)&lt;/p&gt;

&lt;p&gt;Luego tenemos que envolver LoginButtonComponent y LogoutButtonComponent en un solo componente que tiene lógica para decidir qué botón renderizar dependiendo del estado de autenticación del usuario.&lt;/p&gt;

&lt;p&gt;authentication-button.component.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-authentication-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./authentication-button.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./authentication-button.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationButtonComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y su html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;app-login-button&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"(auth.isAuthenticated$ | async) === false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/app-login-button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;app-logout-button&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"auth.isAuthenticated$ | async"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/app-logout-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth0 expone un observable "isAuthenticated$" que emite un valor booleano. Cuando el usuario se ha autenticado el valor es true y cuando no es false.&lt;/p&gt;

&lt;p&gt;Y por último debemos agregar el app-authentication-button a nuestro home-component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;app-authentication-button&amp;gt;&amp;lt;/app-authentication-button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si haz llegado hasta aquí tu implementación básica esta lista y ya puedes correr la aplicación de Angular y probarla.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;serve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando hagas clic en el botón "Log In" serás redirigido a la página de acceso universal de Auth0&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wv7b2oi9w6h19qv2ib6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wv7b2oi9w6h19qv2ib6.png" alt="image" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La primera vez que inicies te solicitara que autorices la aplicación.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49cwhudv0qfdwydls6ia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49cwhudv0qfdwydls6ia.png" alt="image" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si iniciaste sesión correctamente deberías de ver el botón de cierre de sesión.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5si5qogrno6huvt4l9qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5si5qogrno6huvt4l9qk.png" alt="image" width="320" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando termina de iniciar sesión y Auth0 lo redirige a su aplicación Angular, la interfaz de usuario tiene una pantalla en blanco parpadeando.&lt;/p&gt;

&lt;p&gt;La interfaz de usuario parpadea porque su aplicación Angular está cargando sus servicios. Mientras se carga, Angular no sabe si Auth0 ya ha autenticado al usuario. Su aplicación conocerá el estado de autenticación del usuario después de que se cargue Auth0 Angular SDK.&lt;/p&gt;

&lt;p&gt;Para arreglar eso vamos a validar la sesión en el AppComponent utilizando el observable "isLoading$" que provee el AuthService.&lt;/p&gt;

&lt;p&gt;El app.component.ts quedaría así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;angular-login-auth0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y el html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"auth.isLoading$ | async; else loaded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Cargando...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;ng-template&lt;/span&gt; &lt;span class="na"&gt;#loaded&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ng-template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí seria adecuado implementar un componente de "carga" mientras se cargan los servicios.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Recuperar el perfil del usuario&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Después de que el usuario inicia sesión correctamente, Auth0 envía un token de identificación a su aplicación Angular.&lt;/p&gt;

&lt;p&gt;Auth0 utiliza tokens de identificación en la autenticación basada en token para almacenar en caché la información del perfil de usuario y proporcionarla a una aplicación cliente.&lt;/p&gt;

&lt;p&gt;Puede utilizar los datos del token de ID para personalizar la interfaz de usuario de su aplicación de Angular. El Auth0 Angular SDK decodifica el token de ID y emite sus datos a través del Observable. Parte de la información del token de ID incluye el nombre, el nickname, la imagen y el correo electrónico del usuario que inició sesión.&lt;/p&gt;

&lt;p&gt;Creemos un componente para el perfil&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;ng&lt;/span&gt; &lt;span class="err"&gt;g&lt;/span&gt; &lt;span class="err"&gt;c&lt;/span&gt; &lt;span class="err"&gt;pages/profile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El profile.component.ts quedaría de la siguiente manera&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./profile.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./profile.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProfileComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;profileJson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user$&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;profileJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y en el html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;{{profileJson}}&lt;span class="nt"&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahora agregamos una nueva ruta en el app-routing.module.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProfileComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/profile/profile.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/home/home.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProfileComponent&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppRoutingModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando naveguemos a la ruta &lt;a href="http://localhost:4200/profile" rel="noopener noreferrer"&gt;http://localhost:4200/profile&lt;/a&gt;&lt;br&gt;
podremos ver la información del usuario.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;6. Protección de rutas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Auth0 Angular SDK expone un AuthGuard que puede usar para proteger rutas.&lt;/p&gt;

&lt;p&gt;Para requerir que el usuario inicie sesión es tan fácil como agregar la propiedad &lt;strong&gt;canActivate&lt;/strong&gt; a la ruta que queremos proteger y agregar el AuthGuard&lt;/p&gt;

&lt;p&gt;Importemos el AuthGuard en el app-routing.module.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProfileComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/profile/profile.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/home/home.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthGuard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth0/auth0-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HomeComponent&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProfileComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthGuard&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppRoutingModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extra
&lt;/h3&gt;

&lt;p&gt;Si fue curioso pudo notar que cuando ha iniciado sesión con acceso social (Google) y refresca la página la sesión se pierde esto se debe a que las claves de desarrollador Auth0 se están utilizando en lugar de sus propias credenciales para una conexión social.&lt;/p&gt;

&lt;p&gt;En la sección de conexiones sociales del panel de Auth0 podrá configurar sus propias credenciales para resolver este problema. Las claves de desarrollo de Auth0 están diseñadas para pruebas y no se recomiendan para entornos de producción.&lt;/p&gt;

&lt;p&gt;Otra solución es usar &lt;a href="https://auth0.com/docs/tokens/refresh-tokens/refresh-token-rotation" rel="noopener noreferrer"&gt;Refresh Token Rotation&lt;/a&gt; y establecer cacheLocation"localstorage" al inicializar el Auth0 Angular SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;AuthModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;cacheLocation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localstorage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El repositorio con el código de este tutorial lo podrá encontrar &lt;a href="https://github.com/ricardochl/angular-login-auth0" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Conclusión
&lt;/h3&gt;

&lt;p&gt;Hemos implementado la autenticación de usuario en Angular, obtener la información del usuario que inicio sesión y también controlar a que rutas pueden acceder los usuarios.&lt;/p&gt;

&lt;p&gt;Auth0 es una poderosa solución que nos permite agregar los servicios de Autenticación a nuestras aplicaciones de una manera sencilla haciendo la mayor parte del trabajo por nosotros.&lt;/p&gt;

&lt;p&gt;Déjame saber en los comentarios que te pareció este tutorial. &lt;/p&gt;

&lt;p&gt;Gracias por leer está publicación.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>auth0</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Como usar HttpInterceptors en Angular</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Wed, 28 Apr 2021 23:02:11 +0000</pubDate>
      <link>https://forem.com/ricardochl/como-usar-httpinterceptors-en-angular-2o84</link>
      <guid>https://forem.com/ricardochl/como-usar-httpinterceptors-en-angular-2o84</guid>
      <description>&lt;p&gt;Los interceptors en Angular nos brindan un mecanismo para interceptar y/o mutar las solicitudes y respuestas http. No debe confundirse con los Guards. Los interceptors modifican las peticiones del http module.&lt;/p&gt;

&lt;p&gt;Aunque los interceptors son capaces de mutar solicitudes y respuestas, las propiedades HttpRequest y las HttpResponse son read-only, lo que las hace inmutables.&lt;/p&gt;

&lt;p&gt;Disponible desde la versión 4.3 de Angular.&lt;/p&gt;

&lt;p&gt;Los interceptors son capaces de intervenir las solicitudes de entrada y de salida, es decir lo que sale de tu app al servidor y lo que llega del servidor a tu app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51sp8fpfkexj3u234nwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51sp8fpfkexj3u234nwo.png" alt="Alt Text" width="501" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Múltiples Interceptores&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Angular aplica los interceptors en el orden en que los proporcionas. Si proporciona los interceptors A, luego B y luego C, las solicitudes fluirán en A-&amp;gt; B-&amp;gt; C y las respuestas fluirán hacia fuera C-&amp;gt; B-&amp;gt; A.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementación&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para implementar un interceptor se necesita una clase inyectable que implemente “HttpInterceptor”. La clase debe definir un método “intercep”, el cual toma dos argumentos, req y next, y devuelve un observable de tipo HttpEvent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyInterceptor&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpReq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los interceptors se ejecutan en cada petición que se realiza al servidor, para eso deben estar registrados. Para registrar un interceptor se tiene que proveer en el array de providers: [] en nuestro módulo raíz, por lo general AppModule. &lt;/p&gt;

&lt;p&gt;Debemos importar HTTP_INTERCEPTORS y HttpClientModule, quedaría así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HTTP_INTERCEPTORS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyInterceptor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./interceptors/my.interceptor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTTP_INTERCEPTORS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;multi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La mayoría de los interceptors transforman la solicitud saliente antes de pasarla al siguiente interceptor de la cadena, llamando next.handle(transformedReq). Un interceptor también puede transformar el flujo de eventos de respuesta, aplicando operadores RxJS adicionales en el flujo devuelto por next.handle().&lt;/p&gt;

&lt;p&gt;El método "intercept" intercepta y maneja un HttpRequest ó HttpResponse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HttpRequest:&lt;/strong&gt; Una solicitud HTTP saliente con un cuerpo con tipo opcional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HttpResponse:&lt;/strong&gt; Es un HttpEvent disponible en la secuencia de eventos de respuesta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HttpHandler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Transforma una HttpRequest en una secuencia de HttpEvents, una de las cuales probablemente sea HttpResponse.&lt;/p&gt;

&lt;p&gt;La instancia del controlador envía las solicitudes al primer interceptor de la cadena, que envía a la segunda, etc., y finalmente llega al HttpBackend. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HttpBackend:&lt;/strong&gt; Es un HttpHandler final que enviará la solicitud a través de las API HTTP del navegador a un backend.&lt;/p&gt;

&lt;p&gt;HttpEvent: Es un tipo de unión para todos los eventos posibles en el flujo de respuesta.&lt;/p&gt;

&lt;p&gt;HTTP_INTERCEPTORS: Representa la matriz de HttpInterceptors que están registrados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplos de uso&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Autenticación&lt;/li&gt;
&lt;li&gt;Añadir cabeceras extras a las peticiones.&lt;/li&gt;
&lt;li&gt;Almacenar un log de las peticiones realizadas por la aplicación.&lt;/li&gt;
&lt;li&gt;Loading Centralizado.&lt;/li&gt;
&lt;li&gt;Manejador de Errores.&lt;/li&gt;
&lt;li&gt;Notificaciones&lt;/li&gt;
&lt;li&gt;Debug de las respuestas recibidas.
etc...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Puedes encontrar mas ejemplos en este &lt;a href="https://github.com/ricardochl/AngularInterceptors" rel="noopener noreferrer"&gt;repositorio&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
