<?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>DEV Community: Ricardo Chavarria</title>
    <description>The latest articles on DEV Community by Ricardo Chavarria (@ricardochl).</description>
    <link>https://dev.to/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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264740%2F2138d882-de52-4cee-843d-74ef071b6e4a.jpg</url>
      <title>DEV Community: Ricardo Chavarria</title>
      <link>https://dev.to/ricardochl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricardochl"/>
    <language>en</language>
    <item>
      <title>Harness Engineering: el modelo casi nunca es el problema</title>
      <dc:creator>Ricardo Chavarria</dc:creator>
      <pubDate>Tue, 22 Sep 2026 16:52:18 +0000</pubDate>
      <link>https://dev.to/ricardochl/harness-engineering-el-modelo-casi-nunca-es-el-problema-1mg6</link>
      <guid>https://dev.to/ricardochl/harness-engineering-el-modelo-casi-nunca-es-el-problema-1mg6</guid>
      <description>&lt;p&gt;Hace poco monté un experimento pequeño: el mismo modelo de IA, la misma tarea de código, tres configuraciones distintas de lo que tenía permitido hacer. El resultado más revelador no fue que el agente fallara: fue ver, con evidencia en pantalla, que la calidad de lo que produce depende mucho menos del modelo de lo que solemos asumir, y mucho más de la infraestructura que construimos alrededor de él. A eso, en la industria, se le empezó a llamar &lt;em&gt;harness engineering&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los números que motivaron todo esto
&lt;/h2&gt;

&lt;p&gt;A finales de 2025 los mejores agentes de codificación rondaban 50-60% de éxito en SWE-bench Verified, un benchmark que usa tareas curadas con tests ya existentes: el escenario más favorable posible. Anthropic corrió un &lt;a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents" rel="noopener noreferrer"&gt;experimento más incómodo todavía&lt;/a&gt;: el mismo modelo exacto, el mismo prompt, dos configuraciones. Sin ningún andamiaje alrededor: 20 minutos, 9 dólares, el resultado no funcionaba. Con una arquitectura de tres agentes coordinados: 6 horas, 200 dólares, un producto completo y funcional.&lt;/p&gt;

&lt;p&gt;El modelo no cambió entre esas dos corridas. Todo lo demás sí.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué es, en realidad, un harness
&lt;/h2&gt;

&lt;p&gt;La definición más precisa que he encontrado es también la más simple: un harness es todo lo que existe en la infraestructura de ingeniería que rodea a un agente y que &lt;strong&gt;no&lt;/strong&gt; son los pesos del modelo. Si algo no vive dentro de la red neuronal misma, vive en el harness. Dicho como ecuación, agente completo = modelo + harness.&lt;/p&gt;

&lt;p&gt;Esto importa porque cambia dónde uno busca soluciones. El modelo no lo entrenas tú: lo entrena Anthropic, OpenAI, Google. No puedes abrirlo y ajustar un parámetro. El harness sí lo controla por completo el equipo que lo usa, y es ingeniería de software normal: se diseña, se versiona, se prueba, se mejora con datos.&lt;/p&gt;

&lt;p&gt;Una forma de verlo: el modelo es el piloto. El harness es el auto, la pista señalizada, y el equipo en boxes. Un piloto excelente en un auto mal calibrado, sin indicaciones de la pista y sin nadie que le avise el estado de las llantas, va a cometer errores que no tienen nada que ver con su talento al volante. Un piloto correcto (ni excepcional ni torpe) con un auto bien puesto a punto, una pista bien marcada, y un equipo que le confirma en cada vuelta qué está funcionando, corre carreras consistentes. La habilidad del piloto importa, pero deja de ser la variable que decide la carrera.&lt;/p&gt;

&lt;p&gt;Concretamente, esa infraestructura cubre cinco frentes que se sostienen entre sí: qué &lt;strong&gt;instrucciones&lt;/strong&gt; lee el agente al arrancar, qué &lt;strong&gt;herramientas&lt;/strong&gt; tiene permitido usar, qué tan reproducible es el &lt;strong&gt;entorno&lt;/strong&gt; donde trabaja, qué recuerda del &lt;strong&gt;estado&lt;/strong&gt; entre una sesión y la siguiente, y (la que más rendimiento aporta y menos atención recibe) cómo recibe &lt;strong&gt;retroalimentación&lt;/strong&gt; sobre si lo que hizo está bien o mal.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TD
    A[Agente completo] --&amp;gt; I[Instrucciones&amp;lt;br/&amp;gt;qué lee al arrancar]
    A --&amp;gt; H[Herramientas&amp;lt;br/&amp;gt;qué puede ejecutar]
    A --&amp;gt; E[Entorno&amp;lt;br/&amp;gt;qué tan reproducible es]
    A --&amp;gt; S[Estado&amp;lt;br/&amp;gt;qué recuerda entre sesiones]
    A --&amp;gt; R[Retroalimentación&amp;lt;br/&amp;gt;cómo sabe si acertó]

    style A fill:#20344b,color:#ffffff
    style R fill:#5cdb6d,color:#20344b&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Ninguna de las cinco compensa la ausencia de las otras cuatro; un archivo de instrucciones perfecto no sirve de mucho si el agente no tiene forma de verificar que las siguió.&lt;/p&gt;

&lt;p&gt;Un equipo real que documentó su propio proceso lo vivió en carne propia: con solo un README genérico, un agente con GPT-4o resolvía tareas correctamente 1 de cada 5 veces. Agregar un archivo de instrucciones subió eso a 60%. Agregar comandos de verificación explícitos, a 80%. Agregar una plantilla de progreso entre sesiones, terminó estabilizando el resultado entre 80 y 100%. El modelo fue el mismo en las cuatro mediciones: cada punto porcentual de mejora vino de una pieza distinta del harness, no de la red neuronal.&lt;/p&gt;

&lt;h2&gt;
  
  
  El repositorio es la única memoria que cuenta
&lt;/h2&gt;

&lt;p&gt;Hay una idea incómoda detrás de esto: si una convención de tu equipo vive solo en la cabeza de alguien, o en un hilo de Slack de hace tres meses, el agente no tiene forma de saber que existe. No es que la ignore, no puede verla. Por eso la recomendación más repetida en este espacio es tan simple de decir y tan difícil de sostener en la práctica: todo lo que importa tiene que estar escrito, dentro del repo.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    S[Reglas en Slack] --&amp;gt; R[Escríbelas en&amp;lt;br/&amp;gt;archivos del repo]
    C[Reglas en Confluence] --&amp;gt; R
    H[En la cabeza&amp;lt;br/&amp;gt;de alguien] --&amp;gt; R
    J[Tickets de Jira] --&amp;gt; R
    R --&amp;gt; N[Sesión nueva lee&amp;lt;br/&amp;gt;el repo directamente]

    style R fill:#5cdb6d,color:#20344b
    style N fill:#20344b,color:#ffffff&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Una forma práctica de comprobar si ya lo lograste: abre una sesión de agente completamente nueva, sin contexto verbal, y pídele que responda cinco preguntas básicas solo leyendo el repo (qué es el sistema, cómo está organizado, cómo se ejecuta, cómo se verifica, y dónde va el trabajo). Si se traba en alguna, esa es exactamente la zona en blanco donde el agente termina adivinando.&lt;/p&gt;

&lt;p&gt;El problema es que "escribir todo" tiene un límite real. Un equipo dejó crecer su archivo de instrucciones de 50 a 600 líneas, sumando una regla cada vez que el agente se equivocaba en algo. El rendimiento, en vez de mejorar, empezó a caer. La causa no era solo el volumen: era dónde vivía cada regla. Reorganizaron el archivo en un índice corto de 80 líneas que apunta a documentos temáticos separados, y una regla de seguridad crítica que antes estaba enterrada en la línea 300 pasó a estar cerca del principio. Sin cambiar una palabra de esa regla, su cumplimiento subió de 60% a 95%. Hay investigación de 2023 que explica por qué: &lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;"Lost in the Middle"&lt;/a&gt; (Liu et al.) muestra que los modelos usan mucho peor la información que está en medio de un documento largo que la que está al principio o al final.&lt;/p&gt;

&lt;p&gt;Así se ve ese patrón en la práctica, en el archivo de instrucciones que usé para mi propio experimento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# AGENTS.md: Contrato de Ejecución del Repositorio&lt;/span&gt;

Es un mapa, no una enciclopedia. Si necesitas el porqué de una
decisión, no está aquí: está en &lt;span class="sb"&gt;`DECISIONS.md`&lt;/span&gt;.

&lt;span class="gu"&gt;## Reglas arquitectónicas inviolables&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Standalone obligatorio. Ningún NgModule nuevo.
&lt;span class="p"&gt;2.&lt;/span&gt; Signals nativos para estado. Prohibido RxJS para estado local.
&lt;span class="p"&gt;3.&lt;/span&gt; WIP = 1. Solo una funcionalidad en estado "active" a la vez.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ocho líneas que le dicen al agente exactamente qué no negociar, y ningún párrafo explicando por qué: ese contexto vive aparte, y solo se carga si hace falta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué "una cosa a la vez" no es solo buena práctica, es matemática de contexto
&lt;/h2&gt;

&lt;p&gt;Cuando un agente puede tocar cualquier archivo sin límite, tiende a abrir varios frentes al mismo tiempo y no cerrar ninguno bien. Un caso documentado con una API de 8 funcionalidades lo muestra con números: dándole rienda suelta, el agente activó 5 tareas en paralelo, produjo cerca de 800 líneas, y solo 20% de esas líneas pasaban una verificación end-to-end real. Restringido a una funcionalidad a la vez, verificada antes de pasar a la siguiente, produjo una cuarta parte del código, y esa fracción sí funcionaba, terminando más funcionalidades reales al cierre del proyecto que el enfoque abierto.&lt;/p&gt;

&lt;p&gt;Yo lo viví de forma más directa en mi propio experimento. Con un archivo de reglas que restringía explícitamente qué dependencias se podían agregar, el agente evitó importar un módulo de Angular que hubiera sido la solución más obvia para un formulario: sin que yo se lo pidiera en el prompt, lo resolvió de otra forma porque el archivo de reglas no lo permitía. Y cuando terminó su tarea, se detuvo ahí: había otra pendiente en la misma lista, y en vez de empezarla por su cuenta, me avisó que existía y esperó instrucción. Ninguna de esas dos decisiones vino de lo que yo le escribí en el chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Las listas de tareas como estructura de datos, no como nota
&lt;/h2&gt;

&lt;p&gt;El formato que terminé adoptando viene directo de cómo &lt;a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents" rel="noopener noreferrer"&gt;Anthropic describe su propio proceso interno&lt;/a&gt;: cada función pendiente es un objeto con una descripción, los pasos que la verifican, y un campo booleano que dice si pasa o no: nunca decidido por el agente mismo, siempre por el resultado real de un comando. Así se ve una entrada real de mi propio &lt;code&gt;feature_list.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CART-042"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"El descuento por cupón nunca deja el total en negativo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"verification_command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ng 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;"verification_artifact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-run-2026-09-21.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_files"&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="s2"&gt;"src/app/cart.store.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/app/cart.store.spec.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_autonomous_fix_iterations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"passes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;Nada en ese objeto es ambiguo: qué archivos se pueden tocar, qué comando decide si terminó, y un booleano que solo cambia cuando ese comando corre de verdad. Es una diferencia sutil pero importante frente a la forma en que la mayoría de equipos hace seguimiento hoy: una nota de texto tipo "auth hecho, carrito casi listo" es interpretable, y lo interpretable es exactamente lo que un agente nuevo, sin memoria de la sesión anterior, no puede resolver de forma confiable.&lt;/p&gt;

&lt;p&gt;Fíjate en &lt;code&gt;max_autonomous_fix_iterations&lt;/code&gt;. Todo ingeniero que ha usado agentes conoce el escenario contrario: el agente intenta arreglar un test fallido, rompe otra cosa en el intento, lo vuelve a intentar, rompe algo más, y quince minutos después el diff tiene más ruido que la versión con la que empezó. Ese campo es un circuit breaker: después de cinco intentos autónomos sin éxito, el protocolo obliga a detenerse y dejarlo escrito en el handoff para que una persona lo revise, en vez de seguir iterando sin límite. La autonomía de un agente no debería ser indefinida por defecto; debería tener un techo declarado desde el principio.&lt;/p&gt;

&lt;p&gt;Y fíjate también en &lt;code&gt;verification_artifact&lt;/code&gt;. Hay un matiz que vale la pena admitir: el booleano &lt;code&gt;passes&lt;/code&gt; por sí solo no prueba cómo se llegó a él. Si el comando de verificación corre contra mocks, o en un workspace con residuos de una corrida anterior, puede quedar en verde mientras algo real (el contrato de una API que cambió, por ejemplo) sigue roto. La práctica más robusta no es solo guardar si pasó, es guardar el comando exacto, el estado del entorno, y el artefacto de esa ejecución, para poder auditar después si la verificación fue real o solo parecía serlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  El punto más difícil: declarar éxito sin haberlo verificado
&lt;/h2&gt;

&lt;p&gt;Esta es, para mí, la parte más importante de todo el tema, y la que mi propio experimento terminó ilustrando mejor de lo que esperaba. Hay evidencia de hace casi una década (&lt;a href="https://arxiv.org/abs/1706.04599" rel="noopener noreferrer"&gt;Guo et al., 2017&lt;/a&gt;) de que los modelos de lenguaje son sistemáticamente demasiado confiados en sus propias respuestas. Más reciente todavía, Anthropic encontró, en el artículo &lt;a href="https://www.anthropic.com/engineering/harness-design-long-running-apps" rel="noopener noreferrer"&gt;"Harness design for long-running application development"&lt;/a&gt; (marzo de 2026), que cuando se le pide a un agente que evalúe su propio trabajo, tiende a calificarse mejor de lo que lo haría un observador independiente.&lt;/p&gt;

&lt;p&gt;Quise ver qué tan lejos llegaba eso. Le bloqueé a un agente el acceso a terminal por completo, sin ningún archivo de reglas de por medio, y le pedí que resolviera una función de código con un caso borde específico. Sin forma de ejecutar nada, no inventó un resultado a la ligera. Hizo algo más riguroso: trazó a mano, línea por línea, cada una de las cinco pruebas que definían si su implementación estaba correcta, incluyendo un caso de redondeo con arrastre de punto flotante que resolvió bien. Su conclusión, tal cual la escribió:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Los 5 tests deberían pasar [...] No es lo mismo que verlos correr."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lo sabía. Lo dijo con esas palabras. Y aun así, la afirmación que puso primero fue de alta confianza, no una declaración de incertidumbre. Corrí las pruebas después, por mi cuenta: tenía razón en los cinco casos. Pero no lo sabía cuando lo escribió, y la seguridad de esa frase hubiera sonado idéntica si se hubiera equivocado en un solo detalle.&lt;/p&gt;

&lt;p&gt;Esto fue, literalmente, lo que trazó a mano sin poder ejecutarlo:&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;readonly&lt;/span&gt; &lt;span class="nx"&gt;discountAmount&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&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="nf"&gt;subtotal&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="nf"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&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="nf"&gt;couponPercent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;total&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&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="nf"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&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;discountAmount&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&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;El &lt;code&gt;Math.min&lt;/code&gt; evita que el descuento supere el subtotal, el &lt;code&gt;Math.max(0, ...)&lt;/code&gt; evita el total negativo, y el doble redondeo evita el arrastre de punto flotante. Tres líneas, tres decisiones correctas, verificadas con una calculadora mental y no con un intérprete de JavaScript.&lt;/p&gt;

&lt;p&gt;Ahí está, creo, el núcleo real del problema. No es que los agentes adivinen con descuido. Es que un razonamiento cuidadoso y una verificación real producen el mismo tono de certeza hacia afuera, y solo una de las dos tiene evidencia detrás. La solución que se sugiere para esto no es pedirle al agente que sea "más honesto", no funciona, porque el sesgo de autoevaluación es estructural, no una falla de carácter. La solución es exigir, como regla dura del sistema, que ninguna capa de verificación sea opcional: primero que el código compile, después que pase pruebas en tiempo de ejecución, y solo al final, confirmación de extremo a extremo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué "pasan los tests unitarios" no es lo mismo que "funciona"
&lt;/h2&gt;

&lt;p&gt;Ese último nivel importa más de lo que parece. Los tests unitarios, por diseño, aíslan cada pieza y simulan todo lo demás: eso es justo lo que los vuelve ciegos a los problemas que solo aparecen cuando dos componentes se conectan de verdad. Hay un caso documentado de una aplicación de escritorio donde cada capa (interfaz, script intermedio, lógica de negocio) pasaba sus pruebas por separado, y aun así el flujo completo tenía cinco defectos reales: una incompatibilidad de formato entre dos módulos, datos que nunca llegaban a la pantalla, recursos que no se liberaban, comportamiento distinto según el entorno, errores que no se propagaban hasta donde alguien pudiera verlos. Ninguno de los cinco apareció en un test unitario. Todos aparecieron al correr el sistema completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  El código que queda no es lo mismo que el porqué que se pierde
&lt;/h2&gt;

&lt;p&gt;Cuando un agente trabaja varias sesiones sobre el mismo proyecto, lo que queda al final de cada una es el código: el "qué". La razón por la que se eligió una opción y no otra, el "por qué", casi nunca sobrevive al cierre. Una sesión nueva, sin ese contexto, puede terminar "optimizando" una decisión que en realidad fue deliberada.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    subgraph SIN["Sin artefactos de continuidad"]
        direction LR
        A1[Sesión nueva] --&amp;gt; A2[Sin memoria] --&amp;gt; A3[Re-explora&amp;lt;br/&amp;gt;~15 min] --&amp;gt; A4[Puede duplicar&amp;lt;br/&amp;gt;trabajo]
    end
    subgraph CON["Con artefactos de continuidad"]
        direction LR
        B1[Sesión nueva] --&amp;gt; B2[Lee PROGRESS.md +&amp;lt;br/&amp;gt;DECISIONS.md + git log] --&amp;gt; B3[Retoma en&amp;lt;br/&amp;gt;~3 min]
    end

    style A4 fill:#ea4335,color:#ffffff
    style B3 fill:#5cdb6d,color:#20344b&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Un caso real lo muestra con números: un sistema de blog con autenticación, 12 puntos de función, 5 sesiones estimadas. Sin ningún archivo de estado, para la sesión 5 solo se habían completado 7 de las 12 funciones, y 3 de esas tenían errores ocultos por la deriva acumulada. Con un diario de progreso y un registro de decisiones, las 12 quedaron completadas y verificadas en las mismas 5 sesiones, con el tiempo de "reconstrucción" al abrir cada sesión bajando cerca de 78%.&lt;/p&gt;

&lt;p&gt;Hay un fenómeno &lt;a href="https://www.anthropic.com/engineering/harness-design-long-running-apps" rel="noopener noreferrer"&gt;documentado por Anthropic&lt;/a&gt; que explica parte de esto: cuando un agente nota que el contexto de la sesión se está agotando, tiende a apresurarse y saltar verificaciones que normalmente haría. Un buen registro de estado no es solo comodidad para retomar más rápido: reduce las ventanas donde el agente siente esa presión y empieza a cortar esquinas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un dato menos citado: por qué el sistema necesita poder explicarse
&lt;/h2&gt;

&lt;p&gt;Hay una dimensión de esto que se discute menos, y que a mí me pareció de las más aplicables: no basta con que el sistema sepa si algo falló, tiene que poder decir por qué. Un flujo de trabajo con tres roles (uno que planea, uno que genera, uno que evalúa) probó una misma tarea con y sin ese nivel de detalle en la retroalimentación. Sin él, el ciclo se volvía una serie de reintentos a ciegas: 3-4 rondas, cerca de 45 minutos, resultado apenas aceptable. Con un contrato explícito de qué se esperaba y una rúbrica de evaluación concreta, la misma tarea se resolvió en una sola iteración, en unos 15 minutos, con mejor resultado: tres veces más eficiente. El problema, cuando existía, siempre había sido el mismo tipo de tarea: lo que cambió fue si el sistema podía explicarse a sí mismo qué estaba mal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cerrar bien también es parte del trabajo
&lt;/h2&gt;

&lt;p&gt;Una sesión de agente no debería considerarse terminada solo porque el código "funciona". Debería dejar un estado del que cualquiera (humano o el mismo agente en la siguiente sesión) pueda partir sin adivinar: que el build compile, que las pruebas pasen, que quede un registro legible de qué se hizo, que no queden artefactos de depuración regados por el código, y que el siguiente arranque no dependa de reconstruir contexto perdido. Un proyecto real medido a lo largo de 12 semanas sin esa disciplina terminó con poco más de dos tercios de sus builds compilando correctamente, y arranques de sesión que tomaban una hora. Con la disciplina puesta, esos mismos números se mantuvieron cerca del 97% y bajaron a menos de diez minutos.&lt;/p&gt;

&lt;h2&gt;
  
  
  El modelo y la herramienta no son lo mismo que el harness
&lt;/h2&gt;

&lt;p&gt;Vale la pena separar una cosa más: la herramienta que usas para hablar con el agente ya trae consigo parte de esta infraestructura: un sistema de permisos, gestión de la ventana de contexto, acceso a herramientas. Eso no es algo que uno construye. Lo que sí hay que construir es todo lo específico del propio proyecto: qué arquitectura respetar, qué se puede tocar y qué no, qué comando decide si algo está realmente terminado. En mis tres corridas, la herramienta y el modelo fueron exactamente los mismos de principio a fin. La variable que cambió, y la única que explica la diferencia de resultado, fue esa segunda capa.&lt;/p&gt;

&lt;h2&gt;
  
  
  La conclusión práctica
&lt;/h2&gt;

&lt;p&gt;Cuando un agente de código produce algo mal hecho, el reflejo casi universal es pensar en cambiar de modelo. Es, casi siempre, la opción más cara y la menos efectiva. Antes de eso, vale la pena preguntarse si existe un archivo que diga qué reglas seguir, si hay una forma de que el sistema verifique su propio trabajo sin depender de que el agente decida hacerlo, y si esa verificación es realmente obligatoria o solo una posibilidad entre varias. Ese conjunto de decisiones, no los parámetros del modelo, es lo que terminó marcando la diferencia en cada una de mis pruebas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fuentes
&lt;/h2&gt;

&lt;p&gt;Los conceptos, casos de estudio y datos de este artículo se apoyan en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic, &lt;a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents" rel="noopener noreferrer"&gt;Effective harnesses for long-running agents&lt;/a&gt;: el experimento del editor de juegos y el formato de &lt;code&gt;feature_list.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Anthropic, &lt;a href="https://www.anthropic.com/engineering/harness-design-long-running-apps" rel="noopener noreferrer"&gt;Harness design for long-running application development&lt;/a&gt; (marzo 2026): el sesgo de autoevaluación y la ansiedad de contexto.&lt;/li&gt;
&lt;li&gt;Guo, Pleiss, Sun y Weinberger, &lt;a href="https://arxiv.org/abs/1706.04599" rel="noopener noreferrer"&gt;On Calibration of Modern Neural Networks&lt;/a&gt; (2017).&lt;/li&gt;
&lt;li&gt;Liu et al., &lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle: How Language Models Use Long Contexts&lt;/a&gt; (2023).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://walkinglabs.github.io/learn-harness-engineering/" rel="noopener noreferrer"&gt;Learn Harness Engineering&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>softwareengineering</category>
    </item>
    <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://dev.to/ricardochl/adios-karma-hola-vitest-el-futuro-del-testing-en-angular-52h3</link>
      <guid>https://dev.to/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://dev.to/ricardochl/angular-20-y-el-futuro-sin-zonejs-la-revolucion-zoneless-ha-llegado-a-developer-preview-4k5m</link>
      <guid>https://dev.to/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://dev.to/ricardochl/resource-api-en-angular-la-revolucion-declarativa-de-los-datos-asincronicos-3513</link>
      <guid>https://dev.to/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://dev.to/ricardochl/angular-se-reinventa-bienvenido-a-la-era-de-angular-v18-5ac1</link>
      <guid>https://dev.to/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://dev.to/ricardochl/omitir-un-interceptor-de-angular-usando-context-para-http-interceptors-cf0</link>
      <guid>https://dev.to/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://dev.to/ricardochl/novedades-de-angular-v12-1j3n</link>
      <guid>https://dev.to/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://dev.to/ricardochl/como-servir-archivos-estaticos-en-express-271k</link>
      <guid>https://dev.to/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://dev.to/ricardochl/angular-login-with-auth0-4d8l</link>
      <guid>https://dev.to/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://dev.to/ricardochl/como-usar-httpinterceptors-en-angular-2o84</link>
      <guid>https://dev.to/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>
