En el panorama en constante evolución del desarrollo web, GraphQL ha surgido como una alternativa poderosa a las API REST tradicionales, ofreciendo a los clientes la capacidad de solicitar precisamente los datos que necesitan. Sin embargo, esta flexibilidad puede introducir un nuevo conjunto de desafíos, particularmente en lo que respecta a mantener la seguridad de tipos entre el frontend y el backend. Aquí es donde entra en juego graphql-codegen
, una herramienta revolucionaria que automatiza la generación de código tipado a partir de su esquema GraphQL, potenciando su flujo de trabajo de desarrollo y eliminando toda una clase de errores en tiempo de ejecución.
Este artículo servirá como su guía para comprender y dominar graphql-codegen
. Comenzaremos con los conceptos fundamentales, recorreremos un ejemplo práctico paso a paso de cómo configurar la herramienta y exploraremos las mejores prácticas para integrarla en sus proyectos. Al final de esta guía, estará equipado para aprovechar graphql-codegen
para construir aplicaciones más robustas, mantenibles y con seguridad de tipos.
¿Quiere una plataforma integrada todo en uno para que su equipo de desarrolladores trabaje en conjunto con máxima productividad?
Apidog cumple todas sus demandas y reemplaza a Postman a un precio mucho más asequible!
¿Qué es graphql-codegen
y por qué lo necesita?
En esencia, graphql-codegen
es una herramienta de línea de comandos que inspecciona su esquema GraphQL y sus operaciones GraphQL (consultas, mutaciones y suscripciones) y genera código en una variedad de lenguajes. Para el propósito de esta guía para principiantes, nos centraremos en su caso de uso más popular: la generación de tipos y hooks de TypeScript para aplicaciones frontend.
El problema principal que resuelve graphql-codegen
es el proceso tedioso y propenso a errores de escribir manualmente interfaces de TypeScript para las estructuras de datos de su API GraphQL y los resultados de sus consultas. Sin él, los desarrolladores se ven obligados a trabajar con datos sin tipar (perdiendo los beneficios de TypeScript) o a dedicar una cantidad significativa de tiempo a crear y mantener tipos que pueden quedar fácilmente desactualizados a medida que la API evoluciona.
Los beneficios de adoptar graphql-codegen
son múltiples:
- Seguridad de tipos de extremo a extremo: Al generar tipos directamente desde su esquema,
graphql-codegen
asegura que su código frontend esté siempre sincronizado con el modelo de datos de su backend. Esto significa que detecta errores relacionados con tipos en tiempo de compilación, mucho antes de que lleguen a sus usuarios. - Mejora de la experiencia del desarrollador: Con los tipos generados, obtiene funciones como autocompletado y sugerencias inteligentes en su editor de código, lo que hace que el desarrollo sea más rápido y eficiente. ¡Ya no tendrá que adivinar la forma de las respuestas de su API!
- Reducción de código repetitivo (Boilerplate):
graphql-codegen
puede generar no solo tipos, sino también hooks listos para usar para clientes GraphQL populares como Apollo Client y React Query. Esto elimina la necesidad de escribir lógica repetitiva para la obtención de datos. - Mantenibilidad mejorada: Cuando su esquema de API cambia, un simple comando es todo lo que se necesita para regenerar sus tipos. Esto hace que su base de código sea mucho más fácil de mantener y refactorizar con el tiempo.
Este enfoque se alinea perfectamente con la filosofía de desarrollo "schema-first", donde el esquema GraphQL sirve como única fuente de verdad para su API.
Primeros pasos: Su primera configuración de graphql-codegen
Vamos a sumergirnos en los aspectos prácticos del uso de graphql-codegen
. Para este tutorial, asumiremos que tiene una comprensión básica de GraphQL, TypeScript, y que tiene Node.js y un gestor de paquetes (como npm o yarn) instalados.
Nuestro objetivo es configurar graphql-codegen
para una aplicación React simple que muestre una lista de publicaciones de blog.
Paso 1: Inicialización del proyecto y dependencias
Primero, creemos un nuevo proyecto React con TypeScript e instalemos las dependencias necesarias.Bash
npx create-react-app my-blog --template typescript
cd my-blog
npm install @apollo/client graphql
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset typescript
Aquí hay un desglose de las dependencias que hemos instalado:
@apollo/client
: Un cliente GraphQL popular para React.graphql
: Una dependencia par requerida tanto por Apollo Client como porgraphql-codegen
.@graphql-codegen/cli
: La interfaz de línea de comandos paragraphql-codegen
.@graphql-codegen/client-preset
: Un preset moderno y optimizado que simplifica la configuración para aplicaciones del lado del cliente.typescript
: El compilador de TypeScript.
Paso 2: El asistente de inicialización de graphql-codegen
La forma más sencilla de empezar con graphql-codegen
es utilizando su asistente de inicialización. Ejecute el siguiente comando en el directorio raíz de su proyecto:Bash
npx graphql-codegen init
El asistente le hará una serie de preguntas para ayudar a configurar su proyecto. Aquí hay un conjunto típico de respuestas para nuestro escenario de aplicación de blog:
- ¿Qué tipo de aplicación está construyendo?
Application built with React
- ¿Dónde está su esquema? Proporcione la URL a su endpoint de API GraphQL. Para este tutorial, podemos usar una API de ejemplo disponible públicamente:
https://swapi-graphql.netlify.app/.netlify/functions/index
- ¿Dónde están sus operaciones y fragmentos?
src/**/*.tsx
(Esto le dice agraphql-codegen
que busque consultas GraphQL en todos los archivos.tsx
dentro del directoriosrc
). - Seleccione plugins: El asistente sugerirá un conjunto de plugins. Los valores predeterminados, incluyendo
typescript
,typescript-operations
, ytypescript-react-apollo
, son un excelente punto de partida. - ¿Dónde escribir la salida?
src/gql/
(Esto creará un nuevo directoriosrc/gql
para almacenar los archivos generados). - ¿Desea generar un archivo de introspección?
Sí
(Esto puede ser útil para el desarrollo local y extensiones de IDE). - ¿Cómo nombrar el archivo de configuración?
codegen.ts
- ¿Qué script en package.json debería ejecutar el codegen?
codegen
Después de responder estas preguntas, el asistente creará un archivo codegen.ts
en la raíz de su proyecto y agregará un script codegen
a su package.json
.
Paso 3: Comprensión del archivo de configuración (codegen.ts
)
El archivo codegen.ts
es el corazón de su configuración de graphql-codegen
. Echemos un vistazo a una versión simplificada de lo que genera el asistente:TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: []
}
}
};
export default config;
Desglosemos las opciones clave de configuración:
overwrite: true
: Esto asegura que los archivos generados existentes se sobrescriban cada vez que ejecute el comando.schema
: Esto apunta a la fuente de su esquema GraphQL. Puede ser una URL a un endpoint en vivo, un archivo local.graphql
o.json
.documents
: Este es un patrón glob que le dice agraphql-codegen
dónde encontrar sus operaciones GraphQL (consultas, mutaciones y fragmentos).generates
: Esta es la parte más importante de la configuración. Es un objeto donde cada clave representa un archivo o directorio de salida, y el valor define qué generar.preset: "client"
: Elclient-preset
es una forma potente y recomendada de configurargraphql-codegen
para aplicaciones frontend. Agrupa varios plugins y proporciona una experiencia optimizada. Genera una funcióngraphql
que usará para escribir sus consultas.
Paso 4: Escribiendo su primera consulta GraphQL
Ahora que graphql-codegen
está configurado, escribamos una consulta GraphQL para obtener nuestras publicaciones de blog. Cree un nuevo archivo src/components/Posts.tsx
:TypeScript
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
const GET_POSTS = gql(`
query GetPosts {
allFilms {
films {
id
title
director
releaseDate
}
}
}
`);
const Posts = () => {
const { loading, error, data } = useQuery(GET_POSTS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
{data?.allFilms?.films?.map((film) => (
<div key={film?.id}>
<h2>{film?.title}</h2>
<p>Director: {film?.director}</p>
<p>Release Date: {film?.releaseDate}</p>
</div>
))}
</div>
);
};
export default Posts;
Observe que estamos importando una función gql
del archivo generado src/gql/gql.ts
. Esta es la función gql
proporcionada por el client-preset
y es lo que permite la magia de la inferencia de tipos.
Paso 5: Ejecutando graphql-codegen
y viendo la magia
Ahora, ejecute el script codegen
de su package.json
:Bash
npm run codegen
Este comando inspeccionará el esquema, encontrará su consulta GET_POSTS
y generará los tipos de TypeScript correspondientes en el directorio src/gql
.
Si ahora inspecciona el objeto data
devuelto por el hook useQuery
en Posts.tsx
, ¡verá que está completamente tipado! Su IDE proporcionará autocompletado para data.allFilms.films
, y TypeScript le advertirá si intenta acceder a un campo que no existe en la consulta.
Una inmersión más profunda: Un ejemplo práctico de frontend de blog
Ampliemos nuestro ejemplo para consolidar su comprensión. Imagine que nuestro blog tiene un esquema más tradicional:GraphQL
type Author {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
content: String!
author: Author!
}
type Query {
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!, authorId: ID!): Post!
}
Supongamos que este esquema se está ejecutando en http://localhost:4000/graphql
. Actualizaríamos nuestro codegen.ts
en consecuencia:TypeScript
// codegen.ts
// ...
schema: "http://localhost:4000/graphql",
// ...
Ahora, creemos un componente para mostrar una sola publicación y otro para crear una nueva.
Obteniendo una sola publicaciónTypeScript
// src/components/Post.tsx
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
import { useParams } from 'react-router-dom';
const GET_POST = gql(`
query GetPost($id: ID!) {
post(id: $id) {
id
title
content
author {
id
name
}
}
}
`);
const Post = () => {
const { id } = useParams<{ id: string }>();
const { loading, error, data } = useQuery(GET_POST, {
variables: { id },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
<h2>{data?.post?.title}</h2>
<p>By {data?.post?.author?.name}</p>
<p>{data?.post?.content}</p>
</div>
);
};
export default Post;
Después de ejecutar npm run codegen
, se generarán los tipos para la consulta GetPostQuery
y sus variables, proporcionando seguridad de tipos para el hook useQuery
y su resultado.
Creando una nueva publicaciónTypeScript
// src/components/CreatePost.tsx
import { gql } from '../gql/gql';
import { useMutation } from '@apollo/client';
import { useState } from 'react';
const CREATE_POST = gql(`
mutation CreatePost($title: String!, $content: String!, $authorId: ID!) {
createPost(title: $title, content: $content, authorId: $authorId) {
id
}
}
`);
const CreatePost = () => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
createPost({ variables: { title, content, authorId: '1' } }); // Assuming authorId '1' for simplicity
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<textarea
placeholder="Content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create Post'}
</button>
{error && <p>Error creating post: {error.message}</p>}
{data && <p>Post created with ID: {data.createPost.id}</p>}
</form>
);
};
export default CreatePost;
Aquí, graphql-codegen
genera los tipos para la mutación CreatePostMutation
y sus variables. Esto asegura que cuando llame a la función createPost
, esté pasando los tipos correctos para title
, content
y authorId
.
Conceptos avanzados y mejores prácticas
A medida que se sienta más cómodo con graphql-codegen
, encontrará características más avanzadas y mejores prácticas:
Fragmentos: graphql-codegen
tiene un excelente soporte para fragmentos de GraphQL. Puede definir fragmentos en sus archivos .tsx
y graphql-codegen
manejará correctamente los tipos, promoviendo dependencias de datos reutilizables y co-localizadas para sus componentes.
Usando archivos .graphql
: Para una mejor separación de preocupaciones, puede escribir sus consultas, mutaciones y fragmentos de GraphQL en archivos .graphql
dedicados. Simplemente actualice el array documents
en su codegen.ts
para incluir esta extensión de archivo: documents: ["src/**/*.tsx", "src/**/*.graphql"]
.
Escalares personalizados: Si su esquema GraphQL utiliza escalares personalizados (por ejemplo, Date
, JSON
), puede mapearlos a los tipos de TypeScript correspondientes en su archivo codegen.ts
para mantener la seguridad de tipos.
Modo de vigilancia (Watch Mode): Para una experiencia de desarrollo fluida, puede ejecutar graphql-codegen
en modo de vigilancia. Esto regenerará automáticamente sus tipos cada vez que guarde un archivo que contenga una operación GraphQL. Simplemente agregue un flag --watch
a su script codegen
en package.json
: "codegen": "graphql-codegen --watch"
.
Solución de problemas comunes
Aunque graphql-codegen
es una herramienta potente, es posible que encuentre algunos problemas comunes como principiante:
- "No se puede encontrar el esquema" (Unable to find schema): Este error generalmente significa que la ruta
schema
en sucodegen.ts
es incorrecta o que el servidor GraphQL no se está ejecutando en la dirección especificada. - Errores de configuración de plugins: Asegúrese de haber instalado todos los plugins necesarios y de que sus configuraciones en
codegen.ts
sean correctas. - Problemas con la dependencia par
graphql
: Asegúrese de tenergraphql
instalado como una dependencia directa en su proyecto.
Conclusión: Abrace el futuro con seguridad de tipos
graphql-codegen
es más que una simple herramienta de generación de código; es un cambio de paradigma en la forma en que construimos aplicaciones con GraphQL. Al adoptar la automatización y aprovechar el poder de su esquema, puede crear bases de código más robustas, mantenibles y agradables de trabajar.
Este tutorial le ha proporcionado una base sólida para empezar con graphql-codegen
. Hemos cubierto los conceptos centrales, recorrido un ejemplo práctico y abordado las mejores prácticas. El viaje no termina aquí. El ecosistema de graphql-codegen
es vasto, con una rica colección de plugins que atienden a varios frameworks y casos de uso. Le animo a explorar la documentación oficial, experimentar con diferentes plugins y descubrir cómo graphql-codegen
puede revolucionar su flujo de trabajo de desarrollo GraphQL. ¡Feliz codificación!
¿Quiere una plataforma integrada todo en uno para que su equipo de desarrolladores trabaje en conjunto con máxima productividad?
Apidog cumple todas sus demandas y reemplaza a Postman a un precio mucho más asequible!