Conéctate con TwitterConéctate con Facebook
20

Introducción a GraphQL

19986Puntos

hace un año

En 2015 Facebook anunció GraphQL, una tecnología que empezaron a desarrollar y usar internamente en 2012. ¿Pero qué es GraphQL?

Es un lenguaje de queries para definir qué datos queremos pedir a un API. Lo más interesante es que con GraphQL es el cliente, el Frontend, el que decide qué datos pedir y de qué forma al servidor, lo que quiere decir que si mañana necesitamos un dato adicional o dejamos de necesitar un dato no es necesario modificar el Backend, simplemente cambiamos la query de GQL en el cliente y listo.

Algo importante a tener en cuenta es que GraphQL no es una librería o framework. Es una especificación de cómo implementarlo en cualquier lenguaje y a su vez existen implementaciones ya hechas en lenguajes como JavaScript, Ruby, Python, Scala, Java, Clojure, Go, PHP, .NET, etc. También existen clientes para consumir un API GraphQL desde JS, iOS, Android, React, Angular, etc.

Interactuando con GraphQL

Cuando tenemos un API Rest, la forma de interactuar con ella es que hacemos una petición HTTP usando alguno de los métodos, GET, POST, PUT o DELETE, a ciertas URL únicas por recurso del API.

Por ejemplo si hacemo una petición GET /api/careers/ eso nos devuelve la lista de carreras. Si le agregamos /:id podemos pedir los datos de una carrera específica. Así con POST podemos crear nuevas carreras, con PUT y DELETE actualizar y borrar carreras.

En cambio con GQL tenemos un solo endpoint, normalmente /graphql, y solo interactuamos con el mediante el método POST. Para decirle que datos queremos obtener, crear o modificar colocamos en el cuerpo de la petición alguna de estas tres cosas:

  • Query
  • Mutation
  • Subscription

Estas son las 3 formas de interactuar con un API GraphQL. Ahora vamos a ver que es cada una.

Query

El primer concepto importante de GQL es la Query. Una query es básicamente una consulta que hacemos a nuestra API.

query {
	getCourse("id": 1) {
		id
		title
		url
		concepts {
			title
			materials {
				title
				url
			}
		}
	}
}

Ese es un ejemplo de una query para pedir una lista de carreras. De cada carrera pedir el id, el title, el badge, si está approved y sus cursos y los mismos datos de la carrera para cada curso más la URL. Y este es el contenido de la respuesta de dicha query.

{
	"data": {
		"getCourse": {
			"id": 1,
			"title": "Fundamentos de JavaScript",
			"url": "https://platzi.com/clases/fundamentos-javascript/",
			"concepts": [
				...
			]
		}
	}
}

Como vemos, obtenemos un objeto con nuestros datos y dentro tenemos el curso que pedimos al servidor solamente con las propiedades que solicitamos. De esta forma es nuestro cliente quien define los datos que necesita y el servidor simplemente se encargar de responder con esos datos.

La verdad un curso, concepto y material puede tener muchos más datos, pero estos son los únicos que nosotros necesitamos así que, a diferencia de un API Restful, GQL nos devuelve exactamente lo que necesitamos para nuestra UI, ni más ni menos.

Mutation

Las queries nos permiten obtener datos, pero toda aplicación necesita una forma de crear, modificar, eliminar o interactura con estos datos. Estas son llamadas mutaciones. Una mutación es similar a una función, recibe ciertos parámetros, realiza un cambio y devuelve una respuesta.

mutation {
	addToLearningPath(
		"id": 1
	) {
		title
		badge
		approved
		url
	}
}

Esa mutación lo que hace es indicarle a nuestro servidor que queremos agregar a nuestro plan de estudios el curso con el ID 1 y le decimos que nos responda con el título, badge, si ya aprobamos y la URL. La respuesta sería algo así:

{
	"data": {
		"addToLearningPath": {
			"title": "Fundamentos de JavaScript",
			"badge": "https://static.platzi.com/media/achievements/badge-Fundamentos-js.png",
			"approved": false,
			"url": "https://platzi.com/clases/fundamentos-javascript/"
		}
	}
}

La respuesta entonces nos da los datos que pedimos del curso que agregamos al plan de estudios. Luego con esos datos podemos agregar nuestro curso a la UI de un plan de estudios.

Subscription

Otra parte importante de GQL son las suscripciones. Esto no está implementado por todas las librerías para backend ya que recién hace poco se volvió parte oficial de la especificación. Lo que nos permiten las suscripciones es, como su nombre dice, suscribirnos a cambios que ocurran en el servidor.

Por ejemplo, es posible suscribirse a nuevas notificaciones y de esa forma enterarse en tiempo real de lo que ocurre en nuestra aplicación. Básicamente es mantener una conexión por WebSockets. Veamos un ejemplo

subscription {
	notificationOf("type": "answer") {
		id
		type
		data {
			discussion {
				id
				title
			}
			answer {
				author {
					avatar
					username
				}
				date
			}
		}
	}
}

Con esta suscripción podemos empezar a enterarnos cuando nos responden una pregunta. De cada notificación vamos a obtener el ID, el tipo (siempre answer gracias al filtro) y datos específicos como el ID y título de la pregunta y el autor (con su nombre y avatar) y la fecha de la respuesta. Cuando llegue una notificación entonces nos devuelve un objeto similar a este:

{
	"data": {
		"id": 123,
		"type": "answer",
		"data": {
			"discussion": {
				"id": 456,
				"title": "¿Cómo funciona GraphQL?"
			},
			"answer": {
				"author": {
					"avatar": "<url>",
					"username": "sergiodxa"
				},
				"date": "2017-05-28T23:48:27.752Z"
			}
		}
	}
}

Schema

Cuando desarrollamos un APIGQL hay que definir nuestros esquemas (schemas) de datos. Un esquema en GQL es una definición de un tipo de dato o de las formas de obtener e interactuar con estos datos. Por ejemplo podríamos definir un esquema similar a este:

type Course {
	id: Int!
	title: String!
	badge: String!
	approved: Boolean
	url: String!
	description: String
	concepts: [Concept]
}

Así estamos definiendo que en nuestra aplicación existe un objeto de tipo Course que tiene los siguientes datos:

  • id un número, obligatorio
  • title un string, obligatorio
  • badge un string, obligatorio
  • approved un booleano, opcional
  • url un string, obligatorio
  • description un string, opcional
  • concepts una lista de objetos de tipo Concept, opcional

La propiedad concepts es básicamente una relación que indica que un curso tiene varios conceptos. Luego necesitamos definir las posibles formas de obtener este curso.

type Query {
	getCourse(id: Int!): Courses
	getCourses(): [Courses]
}

Esto nos permite ejecutar una query llamada getCourse pasándole un id obtener un único curso o ejecutar getCourses para obtener una lista de todos los cursos. Similar a la query que vimos más arriba. Luego de definir esto necesitamos definir las posibles mutaciones. Las formas de interactuar con nuestra API.

type Mutation {
	addToLearningPath(id: String!): Course
	createCourse(
		title: String!
		badge: String!
		url: String
		description: String
	): Course
	updateCourse(
		title: String
		badge: String
		url: String
		description: String
	): Course
}

Estas mutaciones que definimos en nuestro esquema son las formas de interactuar con nuestros cursos. Podemos agregarlos a nuestro plan de estudios, crear cursos o modificar cursos. También hay que definir a que datos podemos suscribirnos.

type Subscription {
	notificationOf(type: String!): Notification
}

Así definimos las suscripciones, simplemente indicar el nombre, qué parámetros recibo y qué devuelve, igual que las mutaciones. Por último hay que definir nuestro esquema final, que siempre es algo así:

type Schema {
	query: Query
	mutation: Mutation
	subscription: Subscription
}

Simplemente decir que nuestro esquema tiene query, mutation y subscription y que cada uno corresponde con las que definimos antes.

Resolvers

Los esquemas por si solos no hacen nada, solo definen que se puede hacer en nuestra API. Para eso existen los resolvers, funciones que se encargan de procesar cada posible query, mutación o suscripción de nuestra API y responder con los datos necesarios según la definición de nuestro esquema. Por ejemplo algo así:

const getCourse = async id => Course.findById(id)

Esta función de una línea se encarga de, usando el modelo Course de nuestra base de datos, obtener un curso mediante el ID. En este caso estamos pidiendo todos los posibles campos de nuestra tabla curso de la base de datos. Pero es posible (y de hecho es la idea de GQL) pedir a nuestra BD solo los datos que indicó el cliente. Así optimizamos la lectura y escritura de la BD.

GraphiQL

GraphQL tiene su propio IDE, creado por Facebook, llamado GraphiQL (pronunciado grafical), este IDE funciona mediante web mostrándose, normalmente, en la URL de nuestro API cuando entramos desde un navegador y se conecta con nuestros esquemas de datos para mostrarnos documentación del API y nos deja probarlo, dando sugerencias de autocomplete y mostrándonos las respuestas a las distintas peticiones, mutaciones y suscripciones.

GraphiQL

Ahí vemos un ejemplo de como se vé GraphiQL, en la esquina superior izquierda vemos nuestra petición. Abajo tenemos variables y a la derecha los resultados de correr esa petición.

GraphQL vs Restful

Un problema común de los API Rest es que requieren muchas peticiones para obtener todos los datos necesarios en una vista de nuestra aplicación. Lo que suele llevar a que o se hacen estas peticiones o se crean URL personalizadas para responder con todos los datos necesarios, ambos casos tienen problemas, ya que o le estamos consumiendo datos a nuestros usuarios y podemos tardanos mucho en obtener todas las respuestas o estamos creando endpoints en nuestro API que nunca más se van a volver a usar debido a lo personalizado que son.

Ambos problemas son resultos por GraphQL dejando al cliente decidir que datos quiere en cada momento y con una sola URL manejar todas las peticiones, así en vez de crear URLs personalizadas simplemente definimos los posibles datos de nuestro API y como interactuar con el y dejamos el resto al frontend.

Palabras finales

Rest no está muerto. Para comunicación entre servicios de backend todavía puede servir, pero para un API de cara al cliente que se use en web, mobile, desktop, lo que sea, GraphQL tiene muchas ventajas. Y gracias a clientes como Apollo o Relay Modern es muy fácil empezar a usarlo en cualquier tipo de aplicación frontend.

Si quieres aprender más sobre este lenguaje de queries entra ya al Curso de GraphQL.

Sergio Daniel
Sergio Daniel
@sergiodxa

19986Puntos

hace un año

Todas sus entradas
Ordenar por:
3
79747Puntos
un año

Excelente introducción de GraphQL, muy interesante solución para generar API’s dinámicas sin tener una gran cantidad de endpoints y documentar que data entrega cada uno de ellos.

1
272Puntos
un año

Qué base de datos puedo usar para implememtar GraphQL en mi Frontend, Mysql, RethinkDb, etc? O GraphQL también es un motor para guardar datos?

2
19986Puntos
un año

GraphQL no se implemente en el frontend, es en el backend.

Se puede usar la base de datos que quieras, de hecho GrahpQL no tiene por que pegarle a una base de datos, podés usar GraphQL como un intermediario de un API Rest, o de otro API GraphQL, o combinar todo y que un mismo API consuma datos desde varias bases de datos, desde Rest, desde otro GraphQL, archivos en disco, lo que quieras.

0
1732Puntos
un mes

Sergio una duda, al comienzo del post dices que:

Lo más interesante es que con GraphQL es el cliente, el Frontend, el que decide qué datos pedir y de qué forma al servidor…

Pero ahora mencionas que GraphQL se implementa en el backend.

Me queda la duda de si GraphQL tiene una capa en ambos lados, es decir tanto back como front?

Saludos y gran artículo.

0
979Puntos
22 días

Carlos,
A lo que Sergio se refería es que en un escenario Rest habitual el Frontend tenía un listado de recursos que consumir (bajo los definidos verbos HTTP que todos conocemos), solo podía enviar parámetros a esos endpoints y el servidor le devolvía un Rest con tooooda la información solicitada y la no solicitada también:

Por ejemplo: Si solo necesitas el nombre y la fecha de nacimiento de un usuario, un escenario Rest posiblemente te devuelva más que eso (osea, email, dirección, pais, etc).

LA RESPUESTA a tu pregunta
En GraphQL el escenario cambia, es el FrontEnd el que envía al Backend los atributos que necesita (Obviamente debe existir una configuración previa en el backend), por ejemplo, si solo necesita el nombre y la fecha de nacimineto de un usuario, eso es precisamente lo que pide y eso es lo que GraphQL le devuelve.

Espero haber aportado.

Saludos,

1
1290Puntos
un año

Muy buen material Sergio, muchas gracias!

1
1298Puntos
un año

Yo llevo usando API rest desde mis inicios como desarrollador (desde el año pasado) y estoy trabajando con un framework de NodeJs llamado Loopback, en conjunto con AngularJs para el frontend. Hago este comentario porque Loopback, en sus endPoints puede aceptar ciertos parametros para modelar los datos de entrada, y se les llaman filtros.

Es bastante mas complicado que el GraphQL pero un ejemplo seria:

GET /products
con filtros como:

{
	where: {
		state: 'active'//Cumplan la condicion
	},
	order: 'name ASC', // Ordenar por nombre
	limit: 5, //Solo 5 elementos
	skip: 5//Saltar los primeros 5
}

Desde angular se pueden manipular completamente estos filtros con un SDK, sin angular, se pueden colocar dichos filtros directamente en la url

Puede que sea una aproximacion a lo que hace GraphQL, pero es indiscutible que Graph es mucho mas descriptivo 😄

3
19986Puntos
un año

El problema es que esos son hacks para evitar problemas con Rest, al final terminas armando un híbrido entre Rest y GrahpQL pero sin ser 100% GraphQL, para eso mejor usar GQL 😃

0
9 días

Solo para aclarar conceptos.
las Apis, tienen dos caras por decirlo así, el servidor como una capa de datos, y el cliente que cosumira la api, que en teoria también estará en el servidor. Gaphql tiene la misma “estructura” ??. Perdón si no me hago entender.

0
10 meses

Sergio excelente articulo, que api me recomiendas para empezar y que servidor de aplicacion recomiemdas: jboss o tomcat. Yo trabajo con oracle y queremos migrar nuestras app de que estan en OracleForm a web, GraphL seria una buena opción? Te comento que la parte de logica la tenemos bien mapeada en oracle a través de procedimientos y funciones. Gracias.

1
19986Puntos
9 meses

Nunca trabajé con tecnologías Oracle o Java así que no sabría decirte.

0
236Puntos
un año

Excelente artículo!! Intetare usar GrahpQL en futuros proyectos ya que reduciría el tiempo de trabajo en realizar los diferentes endpoints en un API RestFul.

0
25Puntos
9 meses

el uso de GQL implica que todos proceso de cálculos se realiza en el cliente?

1
19986Puntos
8 meses

No necesariamente, cuando realizas una mutación o una query podés hacer lo que quieras.

0
un año

Excelente. ahora mismo estoy planeando los schemas para n nuevo proyecto.

0
103Puntos
8 meses

Hola Sergio.
Nos puedes indicar por favor el grado de complejidad de GraphQL, el tiempo de duración del curso que impartes. Como aplicas GQL a Laravel? Si tienes un nuevo proyecto en laravel puedo generar todo con GQL?
¿Porque el plan mensual no permite Paypal? (?)

Gracias
Quito.- Ecuador

1
19986Puntos
8 meses
  1. Depende ¿Cómo medís la complejidad vos y que te parece complejo? La verdad no es tán difícil de aprender, con lo que hay arriba aprendiste un montón, luego es implementarlo (que depende del lenguaje y librería/framework).
  2. Yo no imparto el curso de GraphQL.
  3. No uso PHP, pero se que hay librerías de PHP y Laravel para GraphQL
  4. Sí podrías hacer tu API con GQL desde el principio.
  5. No trabajo en Platzi, pregunta a [email protected] por eso.
0
4669Puntos
un año

relay modern o apollo?

2
19986Puntos
un año

Apollo FTW, tiene SSR, es muy simple, funciona con React, Angular, Android y iOS y te da herramientas para hacer servidores de GraphQL más fácil.