Tag: GraphQL

  • Configuración y uso de GraphQL en Angular 21 para desarrolladores

    Configuración y uso de GraphQL en Angular 21 para desarrolladores

    Introduccion a GraphQL con Angular 21

    Tiempo estimado de lectura: 4 min
    • GraphQL + Angular 21: consulta declarativa y reactividad granular con Signals para menos deuda técnica.
    • Configuración mínima: providers standalone y Apollo + InMemoryCache para normalización y SSR compatible.
    • Patrón recomendado: convertir Observables a Signals (toSignal) para plantillas limpias; conservar Observables en la capa de servicios.
    • Mutations: usar optimisticResponse y update junto a typePolicies para evitar parpadeos y duplicados.
    • Codegen: generar tipos y servicios Angular; fallos de contrato en compilación, no en runtime.

    Introducción

    Introduccion a GraphQL con Angular 21 es más que “añadir Apollo”: es reconciliar dos ideas que cambian la capa de datos del frontend —consultas declarativas y reactividad granular con Signals— para obtener rendimiento real y menos deuda técnica. En las primeras líneas: esta guía muestra configuración, patrones y criterios prácticos para llevar GraphQL a una app Angular 21 standalone sin convertir el cliente en una pesadilla de suscripciones.

    Resumen rápido (lectores con prisa)

    Qué es: integración de GraphQL con Angular 21 usando Apollo e InMemoryCache para datos tipados y normalizados.

    Cuándo usarlo: vistas que combinan múltiples recursos o requieren minimizar tráfico.

    Por qué importa: menos overfetching/underfetching, tipado end-to-end y caché cliente coherente.

    Cómo funciona (resumen): configura providers standalone, genera tipos con codegen, convierte Observables a Signals para la UI y usa políticas de caché para mutaciones.

    Por qué usar GraphQL con Angular 21

    GraphQL resuelve dos problemas frecuentes frente a REST: overfetching (descargas de datos innecesarios) y underfetching (múltiples llamadas para construir una vista). Angular 21 aporta Signals y providers standalone que facilitan inyectar un cliente GraphQL tipado y consumir datos de forma síncrona en la UI.

    • Peticiones precisas por vista → menos bytes y mejores Core Web Vitals.
    • Tipado end-to-end con GraphQL Code Generator → fallos detectados en compilación.
    • Caché cliente (Apollo) con normalización → menos refetches y estado local coherente.

    Lecturas oficiales: GraphQL, Apollo Angular, Angular Reactivity.

    Configuración mínima en Angular 21 (Standalone + Zoneless)

    Angular 21 favorece providers en app.config.ts. Usaremos Apollo Angular y InMemoryCache para normalización.

    Proveedores (app.config.ts)

    import { ApplicationConfig, inject } from '@angular/core';
    import { provideHttpClient } from '@angular/common/http';
    import { provideApollo } from 'apollo-angular';
    import { HttpLink } from 'apollo-angular/http';
    import { InMemoryCache } from '@apollo/client/core';
    
    export const appConfig: ApplicationConfig = {
      providers: [
        provideHttpClient(),
        provideApollo(() => {
          const httpLink = inject(HttpLink);
          return {
            link: httpLink.create({ uri: '<a href="https://api.example.com/graphql" style="color: #00c2ff !important;">https://api.example.com/graphql</a>' }),
            cache: new InMemoryCache({
              typePolicies: {
                Query: { fields: {} }
              }
            }),
          };
        })
      ]
    };

    Este patrón funciona con SSR/Hydration si añades lógica de serialización del caché (Apollo persist).

    Queries con Signals: patrón recomendado

    Apollo expone Observables. Convierte esos streams a Signals para plantillas libres de | async y suscripciones manuales.

    Consulta ejemplo

    # src/graphql/user.graphql
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        avatar
        projects { id name }
      }
    }

    Componente standalone usando toSignal

    import { Component, inject, input, effect, computed } from '@angular/core';
    import { toSignal } from '@angular/core/rxjs-interop';
    import { GetUserGQL } from './generated/graphql'; // codegen
    import { map } from 'rxjs';
    
    @Component({ standalone: true, template: `...` })
    export class UserCard {
      private gql = inject(GetUserGQL);
      userId = input.required<string>();
    
      // watch() viene del servicio generado por codegen
      private obs = this.gql.watch({ id: this.userId }).valueChanges;
      private result = toSignal(obs);
      user = computed(() => this.result()?.data?.user ?? null);
    
      // reaccionar a cambios del input: refetch en un effect
      effect(() => {
        const id = this.userId();
        if (id) this.gql.fetch({ id }); // o this.gql.watch(...).refetch()
      });
    }

    Criterio: usa toSignal para lectura en la UI; para flujos complejos conserva Observables en la capa de servicios.

    Documentación codegen: https://www.graphql-code-generator.com/

    Mutations y estrategias de caché

    Para mutaciones, usa async/await, optimisticResponse y update para evitar parpadeos:

    await this.apollo.mutate({
      mutation: UPDATE_USER_NAME,
      variables: { id, name },
      optimisticResponse: { updateUser: { __typename: 'User', id, name } },
      update: (cache, { data }) => {
        cache.modify({
          id: cache.identify({ __typename: 'User', id }),
          fields: { name: () => data.updateUser.name }
        });
      }
    });

    TypePolicies y keyFields son esenciales para normalizar y evitar duplicados. Documentación InMemoryCache: InMemoryCache

    Codegen y contrato cliente-servidor

    No escribas interfaces a mano. GraphQL Code Generator genera:

    • Tipos TypeScript exactos.
    • Servicios Angular (watch/mutate) listos para inyectar.

    Ejemplo codegen.ts:

    schema: "<a href="https://api.example.com/graphql" style="color: #00c2ff !important;">https://api.example.com/graphql</a>",
    documents: "src/**/*.graphql",
    generates: { "src/generated/": { plugins: ["typescript","typescript-operations","typescript-apollo-angular"] } }

    Esto convierte errores de contrato en fallos de build, no bugs runtime.

    ¿Cuándo elegir GraphQL en Angular 21?

    Úsalo si:

    • Vistas combinan datos de múltiples recursos.
    • Móviles requieren minimizar tráfico.
    • Equipo backend provee un grafo unificado.

    Evítalo si:

    • App es CRUD simple (HttpClient es más liviano).
    • Necesitas caching CDN agresivo con rutas REST estáticas.
    • Equipo no puede mantener esquema y codegen sincronizados.

    Buenas prácticas rápidas

    • Versiona y valida tu esquema en CI.
    • Ejecuta codegen en CI; falla la build si tipos cambian inesperadamente.
    • Define typePolicies tempranamente (pagination, merge).
    • Monitoriza latencia y cache hit-rate (Apollo DevTools).
    • Considera BFF si tu backend no puede evolucionar a GraphQL.

    Esta introduccion a GraphQL con Angular 21 es práctica: configura, genera tipos y consume con Signals. No es mágico, pero reduce considerablemente deuda técnica cuando se aplica con criterio. En Dominicode veremos patrones avanzados (cursor pagination, cache eviction, SSR hydration) —esto no acaba aquí.

    FAQ

    1. ¿Qué problemas resuelve GraphQL frente a REST?
    2. ¿Por qué usar Signals en Angular 21 con GraphQL?
    3. ¿Cómo evito parpadeos cuando actualizo datos?
    4. ¿Qué aporta GraphQL Code Generator al flujo de trabajo?
    5. ¿Es Apollo obligatorio?
    6. ¿Cómo encaja esto con SSR y Hydration?

    Respuesta: Reduce overfetching y underfetching al permitir peticiones precisas por vista; evita múltiples llamadas necesarias para componer una UI.

    Respuesta: Signals permiten lectura síncrona en plantillas sin pipes ni suscripciones manuales; facilitan reactividad granular y menos complejidad en la UI.

    Respuesta: Usa optimisticResponse y la función update del cliente para modificar el caché inmediatamente; define typePolicies para mantener consistencia y evitar duplicados.

    Respuesta: Genera tipos TypeScript y servicios Angular que detectan errores de contrato en build; evita escribir interfaces manualmente y reduce bugs runtime.

    Respuesta: No es obligatorio. Apollo aporta InMemoryCache y herramientas maduras para normalización; podrías usar otro cliente GraphQL, pero perderías integraciones y patrones documentados aquí.

    Respuesta: Funciona con SSR/Hydration si serializas y rehidratas el caché (Apollo persist), y si colocas providers correctamente en el arranque standalone de Angular 21.

  • Implementando GraphQL con Angular 21 para un Desarrollo Eficiente

    Implementando GraphQL con Angular 21 para un Desarrollo Eficiente

    Introduccion a GraphQL con Angular 21

    Introduccion a GraphQL con Angular 21 empieza por entender que hoy no se trata solo de consumir APIs: se trata de pedir exactamente lo que la vista necesita y mantener la reactividad fina sin complejidad innecesaria. Angular 21 trae Signals y una configuración standalone que encajan con GraphQL: tipado fuerte, caché normalizado y consultas que reducen overfetching. Aquí tienes una guía práctica, lista para producción.

    Resumen rápido (lectores con prisa)

    Qué es: GraphQL es un lenguaje de consultas para APIs que permite pedir exactamente los campos necesarios.
    Cuándo usarlo: cuando las vistas requieren datos compuestos de múltiples fuentes o pagar ancho de banda es crítico.
    Por qué importa: reduce overfetching, mejora el tipado end-to-end y facilita cache client-side.
    Cómo funciona (breve): un solo endpoint, consultas declarativas, caché normalizado en cliente y generación de tipos para seguridad en tiempo de compilación.

    Tiempo estimado de lectura: 4 min

    Ideas clave

    • Usar GraphQL con Angular 21 permite pedir solo lo necesario y aprovechar Signals para reactividad limpia.
    • Configurar Apollo con InMemoryCache y typePolicies reduce refetches y duplicados.
    • GraphQL Code Generator entrega tipos y servicios fuertemente tipados para workflows seguros.

    Por qué usar GraphQL con Angular 21

    GraphQL flexibiliza la capa de datos: una sola endpoint, consultas declarativas y capacidad para definir con precisión los campos necesarios. Angular 21 aporta Signals y providers standalone que simplifican la inyección del cliente GraphQL y minimizan la verbosidad.

    Beneficios concretos

    • Menos overfetching → mejores Core Web Vitals.
    • Tipado end-to-end con GraphQL Code Generator → errores detectados en compilación.
    • Caché de cliente (Apollo) que normaliza y reduce refetches.

    Lecturas recomendadas: Apollo Angular, Angular, GraphQL Code Generator.

    Configuración inicial (standalone)

    Instala dependencias

    npm install apollo-angular @apollo/client graphql
    npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-apollo-angular

    Proveedores en app.config.ts (o main.ts)

    Ejemplo de configuración de Apollo usando providers standalone:

    import { ApplicationConfig, inject } from '@angular/core';
    import { provideHttpClient } from '@angular/common/http';
    import { provideApollo } from 'apollo-angular';
    import { HttpLink } from 'apollo-angular/http';
    import { InMemoryCache } from '@apollo/client/core';
    
    export const appConfig: ApplicationConfig = {
      providers: [
        provideHttpClient(),
        provideApollo(() => {
          const httpLink = inject(HttpLink);
          return {
            link: httpLink.create({ uri: 'https://tu-api.com/graphql' }),
            cache: new InMemoryCache({
              typePolicies: {
                Query: { fields: {} }
              }
            })
          };
        })
      ]
    };

    Esta aproximación evita NgModule y funciona bien con SSR/PRERENDER.

    Queries con Signals: patrón recomendado

    Apollo devuelve Observables. En Angular 21, convierte esos streams a Signals para consumirlos en plantilla sin | async.

    Consulta GraphQL ejemplo

    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        email
        projects { id name }
      }
    }

    Componente standalone

    import { Component, inject, input } from '@angular/core';
    import { toSignal } from '@angular/core/rxjs-interop';
    import { Apollo } from 'apollo-angular';
    import { map } from 'rxjs';
    import { GET_USER } from '../graphql/queries';
    
    @Component({ selector: 'app-user', standalone: true, template: `...` })
    export class UserComponent {
      private apollo = inject(Apollo);
      userId = input.required();
    
      profile = toSignal(
        this.apollo.watchQuery({ query: GET_USER, variables: { id: this.userId() } })
          .valueChanges.pipe(map(r => r.data)),
        { initialValue: null }
      );
    }

    Consejo práctico: envuelve la creación de la query en un computed si userId puede cambiar y quieres que la query se reactive sin re-suscripciones manuales.

    Mutations, optimismo y caché

    Para mutaciones usa firstValueFrom o async/await y actualiza el caché para reflejar cambios sin refetch.

    import { firstValueFrom } from 'rxjs';
    
    async updateName(id: string, name: string) {
      await firstValueFrom(this.apollo.mutate({
        mutation: UPDATE_USER_NAME,
        variables: { id, name },
        optimisticResponse: { updateUser: { id, name, __typename: 'User' } },
        update: (cache, { data }) => {
          cache.modify({ id: cache.identify({ __typename: 'User', id }), fields: { name: () => name }});
        }
      }));
    }

    Optimistic UI + update evita parpadeos y mejora la percepción de velocidad.

    Generación de tipos y servicios (GraphQL Code Generator)

    No escribas interfaces a mano. Configura Codegen:

    Configuración de Codegen

    // codegen.ts
    import type { CodegenConfig } from '@graphql-codegen/cli';
    const config: CodegenConfig = {
      schema: "https://tu-api.com/graphql",
      documents: "src/**/*.graphql",
      generates: {
        "src/gql/": {
          plugins: ["typescript", "typescript-operations", "typescript-apollo-angular"]
        }
      }
    };
    export default config;

    Resultado: tipos y servicios Angular fuertemente tipados, menos boilerplate y refactors seguros.

    Buenas prácticas y observabilidad

    • Normaliza InMemoryCache con typePolicies y keyFields para evitar duplicados.
    • Añade errorLink y retryLink para manejo global de errores.
    • Etiqueta mutaciones/queries (o usa headers) para correlación en logs.
    • En CI, ejecuta Codegen y fallar la build si los tipos cambian.
    • En desarrollo, usa whitelisting de clientes o modos sandbox para no spamear usuarios reales.

    ¿Cuándo elegir GraphQL con Angular 21?

    Usa GraphQL si tus vistas requieren datos compuestos de múltiples fuentes, necesitas minimizar tráfico en móviles o buscas tipado estricto entre cliente y servidor. No lo añadas por moda: para CRUDs simples o equipos sin experiencia, HttpClient sigue siendo más directo.

    GraphQL con Angular 21 no es mágico; es una herramienta que reduce deuda cuando se aplica con criterio. En Dominicode seguiremos profundizando en patterns avanzados: cache eviction, pagination cursor-based y estrategias para SSR con hydration. Esto no acaba aquí.

    FAQ

    Signals permiten convertir streams en valores reactivos fáciles de usar en plantillas, eliminando la necesidad de | async y simplificando la gestión de suscripciones.
    Sí, normalizar con typePolicies y keyFields evita duplicados y facilita updates locales sin refetch. En APIs simples puede no ser crítico, pero es buena práctica en apps complejas.
    Usa optimisticResponse y la función update del cliente para aplicar cambios al caché de forma inmediata y consistente con la estructura de datos.
    Genera tipos y servicios fuertemente tipados que reducen boilerplate y permiten detectar cambios incompatibles en la compilación, mejorando la seguridad de refactors.
    No. Para CRUDs simples o equipos sin experiencia en GraphQL, HttpClient puede ser más directo. GraphQL brilla cuando las vistas requieren datos compuestos o se busca minimizar tráfico y overfetching.