Creación de API GraphQL sin servidor en Node con Express y Netlify

Índice
  1. Un resumen de los conceptos de API
  2. Concepto 2: sin servidor
  3. Eligiendo nuestras herramientas
  4. ¡Vamos a construir!
  5. Estructura de archivos
  6. Definiendo el esquema GraphQL
  7. Ejecutando el servidor localmente
  8. Bonificación: redireccionamiento de solicitudes
  9. Deploying the API
  10. Conclusion

Siempre quise crear una API, pero me asustó lo complicadas que parecían las cosas. Había leído muchos tutoriales que comienzan con “primero, instale esta biblioteca y esta biblioteca y esta biblioteca” sin explicar por qué eso era importante. Soy una especie de ludita cuando se trata de estas cosas.

Bueno, recientemente me arremangué y me ensucié las manos. Quería crear e implementar una API simple de solo lectura y, Dios mío , no iba a dejar que algunas listas de dependencias aterradoras y servicios sofisticados de vanguardia me detuvieran ¹ .

Lo que descubrí es que debajo de muchos de los tutoriales y proyectos hay un conjunto pequeño y fácil de entender de herramientas y técnicas. En menos de una hora y con sólo 30 líneas de código, creo que cualquiera puede escribir e implementar su propia API de solo lectura. No es necesario ser un ingeniero senior de pila completa: todo lo que necesita es un conocimiento básico de JavaScript y algo de experiencia con npm.

Al final de este artículo podrás implementar tu propia API sin el dolor de cabeza de administrar un servidor. Enumeraré cada dependencia y explicaré por qué la incorporamos. También le daré una introducción a algunos de los conceptos más nuevos involucrados y le proporcionaré enlaces a recursos para profundizar.

¡Empecemos!

Un resumen de los conceptos de API

Hay un par de formas comunes de trabajar con API. Pero comencemos explicando (muy brevemente) de qué se trata una API: leer y actualizar datos.

Durante los últimos 20 años, han surgido algunas formas estándar de crear API. REST (abreviatura de RE Presentational State T ransfer ) es uno de los más comunes. Para utilizar una API REST, realiza una llamada a un servidor a través de una URL (digamos api.example.com/rest/books) y espera obtener una lista de libros en un formato como JSON o XML. Para obtener un solo libro, regresaríamos al servidor en una URL (como api.example.com/rest/books/123) y esperaríamos los datos del libro n.° 123. Agregar un libro nuevo o actualizar los datos de un libro específico significa más viajes al servidor en URL similares definidas con un propósito.

Esa es la idea básica de dos conceptos que veremos aquí: GraphQL y Serverless .

GrafoQL

Las aplicaciones que obtienen y actualizan datos en gran medida realizan muchas llamadas a la API. El software complicado, como Twitter, puede realizar cientos de llamadas para obtener los datos de una sola página. Recopilar los datos correctos de un puñado de URL y formatearlas puede ser un verdadero dolor de cabeza. En 2012, los desarrolladores de Facebook comenzaron a buscar nuevas formas de obtener y actualizar datos de manera más eficiente.

Su idea clave fue que, en su mayor parte, los datos en aplicaciones complicadas tienen relaciones con otros datos. Un usuario tiene seguidores, que son cada uno de ellos, cada uno de los cuales tiene sus propios seguidores, y esos seguidores tienen tweets, que tienen respuestas de otros usuarios. Dibujar las relaciones entre los resultados de los datos en un gráfico y ese gráfico puede ayudar a un servidor a realizar una gran cantidad de trabajo inteligente formateando y enviando (o actualizando) datos, y ahorrando tiempo y frustración a los desarrolladores de aplicaciones para el usuario. Nació Graph Query Language, también conocido como GraphQL.

GraphQL se diferencia del enfoque de API REST en el uso de URL y consultas. Para obtener una lista de libros de nuestra API usando GraphQL, no necesitamos ir a una URL específica (como nuestra api.example.com/graphql/books example). En su lugar, llamamos a la API en el nivel superior (que sería api.example.com/graphqlen nuestro ejemplo) y le decimos qué tipo de información queremos recuperar con un objeto JSON:

{  books {    id    title    author  }}

El servidor ve esa solicitud, formatea nuestros datos y los envía de vuelta en otro objeto JSON:

{  "books" : [    {      "id" : 123      "title" : "The Greatest CSS Tricks Vol. I"      "author" : "Chris Coyier"    }, {      // ...    }  ]}

Sebastian Scholl compara GraphQL con REST utilizando un cóctel ficticio que deja la distinción muy clara. En resumen: GraphQL nos permite solicitar los datos exactos que queremos, mientras que REST nos proporciona un volcado de todo en la URL.

Concepto 2: sin servidor

Cada vez que veo la palabra “sin servidor”, pienso en la famosa pegatina de Chris Watterston.

De manera similar, no existe una aplicación verdaderamente “sin servidor”. Chris Coyier resume bien su publicación “Sin servidor” :

Me parece que lo que intenta significar sin servidor es una nueva forma de administrar y pagar por los servidores. No compras servidores individuales. No los gestionas. No los escalas. No los equilibras. No eres realmente responsable de ellos. Sólo pagas por lo que usas.

El enfoque sin servidor facilita la creación e implementación de aplicaciones back-end. Es especialmente fácil para personas como yo que no tienen experiencia en desarrollo back-end. En lugar de dedicar mi tiempo a aprender cómo aprovisionar y mantener un servidor, a menudo le dejo el trabajo duro a otra persona (o incluso a algo).

Vale la pena consultar la guía CSS-Tricks para todo lo relacionado con la tecnología sin servidor . En la página de Ideas , incluso hay un enlace a un tutorial sobre cómo crear una API sin servidor .

Eligiendo nuestras herramientas

Si explora esa guía sin servidor, verá que no faltan herramientas y recursos para ayudarnos en nuestro camino hacia la creación de una API. Pero exactamente cuáles utilizamos requiere cierta reflexión y planificación inicial. Voy a cubrir dos herramientas específicas que usaremos para nuestra API de solo lectura.

Herramienta 1: NodeJS y Express

Nuevamente, no tengo mucha experiencia con el desarrollo web back-end. Pero una de las pocas cosas que he encontrado es Node.js. Muchos de ustedes probablemente lo conocen y saben lo que hace, pero es esencialmente JavaScript que se ejecuta en un servidor en lugar de un navegador web. Node.js es perfecto para alguien que viene del lado del desarrollo front-end porque podemos trabajar directamente en JavaScript (con defectos y todo) sin tener que recurrir a algún lenguaje de back-end.

Express es uno de los marcos más populares para Node.js. Antes de que React fuera el rey (¿Cómo están, compañeros niños?), Express era la opción ideal para crear aplicaciones web. Hace todo tipo de cosas útiles como enrutamiento, creación de plantillas y manejo de errores.

Seré honesto: marcos como Express me intimidan. Pero para ser una API simple, Express es extremadamente fácil de usar y comprender. Hay un asistente GraphQL oficial para Express y una biblioteca plug-and-play para crear una aplicación sin servidor llamada serverless-http . Genial, ¿verdad?

Herramienta 2: funciones de Netlify

La idea de ejecutar una aplicación sin mantener un servidor suena demasiado buena para ser verdad. Pero mira esto: no sólo puedes lograr esta hazaña de la hechicería moderna, sino que también puedes hacerlo gratis . Alucinante.

Netlify ofrece un plan gratuito con funciones sin servidor que le brindarán hasta 125.000 llamadas API en un mes. Amazon ofrece un servicio similar llamado Lambda . Nos quedaremos con Netlify para este tutorial.

Netlify incluye Netlify Dev , que es una CLI para la plataforma de Netlify. Básicamente, nos permite ejecutar una simulación en un entorno de producción con todas las funciones, todo dentro de la seguridad de nuestra máquina local. Podemos usarlo para crear y probar nuestras funciones sin servidor sin necesidad de implementarlas.

En este punto, creo que vale la pena señalar que no todos están de acuerdo en que ejecutar Express en una función sin servidor sea una buena idea. Como explica Paul Johnston , si está creando funciones a escala, es mejor dividir cada pieza de funcionalidad en su propia función de propósito único. Usar Express como lo he hecho significa que cada vez que una solicitud va a la API, todo el servidor Express debe iniciarse desde cero, lo que no es muy eficiente. Realice la implementación en producción bajo su propia responsabilidad.

¡Vamos a construir!

Ahora que contamos con las herramientas necesarias, podemos iniciar el proyecto. Comencemos creando una nueva carpeta, navegando hasta que encaje en la terminal y luego ejecutémosla npm init . Una vez que npm crea un package.jsonarchivo, podemos instalar las dependencias que necesitamos. Esas dependencias son:

  1. Expresar
  2. GraphQL y express-graphql. Estos nos permiten recibir y responder a solicitudes de GraphQL.
  3. Analizador de cuerpo. Esta es una pequeña capa que traduce las solicitudes que recibimos hacia y desde JSON, que es lo que espera GraphQL.
  4. Sin servidor-http. Esto sirve como un contenedor para Express que garantiza que nuestra aplicación se pueda utilizar en una plataforma sin servidor, como Netlify.

¡Eso es todo! Podemos instalarlos todos en un solo comando:

npm i express express-graphql graphql body-parser serverless-http

También necesitamos instalar Netlify Dev como una dependencia global para poder usarlo como CLI:

npm i -g netlify-cli

Estructura de archivos

Hay algunos archivos necesarios para que nuestra API funcione correctamente. El primero es netlify.tomlel que debe crearse en el directorio raíz del proyecto. Este es un archivo de configuración para decirle a Netlify cómo manejar nuestro proyecto. Esto es lo que necesitamos en el archivo para definir nuestro comando de inicio, nuestro comando de compilación y dónde se encuentran nuestras funciones sin servidor:

[build]
  # This command builds the site  command = "npm run build"
  # This is the directory that will be deployed  publish = "build"
  # This is where our functions are located  functions = "functions"

Esa functionslínea es súper importante; le dice a Netlify dónde colocaremos nuestro código API.

A continuación, creemos esa /functionscarpeta en la raíz del proyecto y creemos un nuevo archivo dentro de ella llamado api.js. Ábralo y agregue las siguientes líneas en la parte superior para que nuestras dependencias estén disponibles para su uso y se incluyan en la compilación:

const express = require("express");const bodyParser = require("body-parser");const expressGraphQL = require("express-graphql");const serverless = require("serverless-http");

Configurar Express solo requiere unas pocas líneas de código. Primero, pondremos las iniciales de Express y lo envolveremos en la serverless-httpfunción sin servidor:

const app = express();module.exports.handler = serverless(app);

Estas líneas inicializan Express y lo envuelven en la serverless-httpfunción. module.exports.handlerle permite a Netlify saber que nuestra función sin servidor es la función Express.

Ahora configuremos Express en sí:

app.use(bodyParser.json());app.use(  "/",  expressGraphQL({    graphiql: true  }));

Estas dos declaraciones le dicen a Express qué middleware estamos ejecutando. El middleware es lo que queremos que suceda entre la solicitud y la respuesta. En nuestro caso, queremos analizar JSON usando bodyparsery manejarlo con express-graphql. La configuración de Graphiql:true express-graphqlnos brindará una interfaz de usuario agradable y un área de juegos para realizar pruebas.

Definiendo el esquema GraphQL

Para comprender las solicitudes y dar formato a las respuestas, GraphQL necesita saber cómo se ven nuestros datos. Si ha trabajado con bases de datos, entonces sabrá que este tipo de modelo de datos se llama esquema. GraphQL combina este esquema bien definido con tipos , es decir, definiciones de diferentes tipos de datos, para hacer su magia.

Lo primero que necesita nuestro esquema se llama consulta raíz. Esto manejará cualquier solicitud de datos que llegue a nuestra API. Se llama consulta “raíz” porque se accede a ella desde la raíz de nuestra API, digamos, api.example.com/graphql.

Para esta demostración, crearemos un ejemplo de hola mundo; la consulta raíz debería dar como resultado una respuesta de “Hola mundo”.

Por lo tanto, nuestra API GraphQL necesitará un esquema (compuesto de tipos) para la consulta raíz. GraphQL proporciona algunos tipos listos para usar, incluidos a schema, a generic object² y a string.

Consigámoslos agregando esto debajo de las importaciones:

const {  GraphQLSchema,  GraphQLObjectType,  GraphQLString} = require("graphql");

Luego definiremos nuestro esquema de esta manera:

const schema = new GraphQLSchema({  query: new GraphQLObjectType({    name: 'HelloWorld',    fields: () = ({ /* we'll put our response here */ })  })})

El primer elemento del objeto, con la clave query, le dice a GraphQL cómo manejar una consulta raíz. Su valor es un objeto GraphQL con la siguiente configuración:

  • name– Una referencia utilizada con fines de documentación.
  • fields– Define los datos con los que nuestro servidor responderá. Puede parecer extraño tener una función que simplemente devuelva un objeto aquí, pero esto nos permite usar variables y funciones definidas en otra parte de nuestro archivo sin necesidad de definirlas primero ³ .
const schema = new GraphQLSchema({  query: new GraphQLObjectType({    name: "HelloWorld",    fields: () = ({      message: {        type: GraphQLString,        resolve: () = "Hello World",      },    }),  }),});

La fieldsfunción devuelve un objeto y nuestro esquema solo tiene un messagecampo hasta ahora. El objeto messagecon el que queremos responder es una cadena, por lo que especificamos su tipo como GraphQLString. Nuestro servidor ejecuta la función de resolución para generar la respuesta que queremos. En este caso, solo devolvemos “Hola mundo”, pero en una aplicación más complicada, probablemente usaríamos esta función para ir a nuestra base de datos y recuperar algunos datos.

¡Ese es nuestro esquema! Necesitamos informarle a nuestro servidor Express al respecto, así que abramos api.jsy asegurémonos de que la configuración Express esté actualizada a esto:

app.use(  "/",  expressGraphQL({    schema: schema,    graphiql: true  }));

Ejecutando el servidor localmente

Lo creas o no, ¡estamos listos para iniciar el servidor! Ejecute netlify deven Terminal desde la carpeta raíz del proyecto. Netlify Dev leerá la netlify.tomlconfiguración, agrupará su api.jsfunción y la pondrá a disposición localmente desde allí. Si todo va según lo planeado, verá un mensaje como “El servidor ya está listo http://localhost:8888“.

Si haces localhost:8888lo mismo que hice yo la primera vez, es posible que te decepciones un poco al recibir un error 404.

¡Pero no temas! Netlify está ejecutando la función, solo que en un directorio diferente al esperado, que es /.netlify/functions. Entonces, si va a localhost:8888/.netlify/functions/api, debería ver la interfaz GraphiQL como se esperaba. ¡Éxito!

La pantalla que aparece es el área de juegos GraphiQL y podemos usarla para probar la API. Primero, borre los comentarios en el panel izquierdo y reemplácelos con lo siguiente:

{  message}

Esto puede parecer un poco… simple… ¡pero acabas de escribir una consulta GraphQL! Lo que estamos diciendo es que nos gustaría ver el campo de mensaje que definimos en api.js. Haga clic en el botón “Ejecutar” y, a la derecha, verá lo siguiente:

{  "data": {    "message": "Hello World"  }}

No sé ustedes, pero yo hice un pequeño movimiento con el puño cuando hice esto la primera vez. ¡Construimos una API!

Bonificación: redireccionamiento de solicitudes

One of my hang-ups while learning about Netlify’s serverless functions is that they run on the /.netlify/functions path. It wasn’t ideal to type or remember it and I nearly bailed for another solution. But it turns out you can easily redirect requests when running and deploying on Netlfiy. All it takes is creating a file in the project’s root directory called _redirects (no extension necessary) with the following line in it:

/api /.netlify/functions/api 200!

This tells Netlify that any traffic that goes to yoursite.com/api should be sent to /.netlify/functions/api. The 200! bit instructs the server to send back a status code of 200 (meaning everything’s OK).

Deploying the API

To deploy the project, we need to connect the source code to Netlfiy. I host mine in a GitHub repo, which allows for continuous deployment.

After connecting the repository to Netlfiy, the rest is automatic: the code is processed and deployed as a serverless function! You can log into the Netlify dashboard to see the logs from any function.

Conclusion

Just like that, we are able to create a serverless API using GraphQL with a few lines of JavaScript and some light configuration. And hey, we can even deploy — for free.

The possibilities are endless. Maybe you want to create your own personal knowledge base, or a tool to serve up design tokens. Maybe you want to try your hand at making your own PokéAPI. Or, maybe you’re interesting in working with GraphQL.

Regardless of what you make, it’s these sorts of technologies that are getting more and more accessible every day. It’s exciting to be able to work with some of the most modern tools and techniques without needing a deep technical back-end knowledge.

If you’d like to see at the complete source code for this project, it’s available on GitHub.

Some of the code in this tutorial was adapted from Web Dev Simplified’s “Learn GraphQL in 40 minutes” article. It’s a great resource to go one step deeper into GraphQL. However, it’s also focused on a more traditional server-full Express.


  1. If you’d like to see the full result of my explorations, I’ve written a companion piece called “A design API in practice” on my website.
  2. The reasons you need a special GraphQL object, instead of a regular ol’ vanilla JavaScript object in curly braces, is a little beyond the scope of this tutorial. Just keep in mind that GraphQL is a finely-tuned machine that uses these specialized types to be fast and resilient.
  3. Scope and hoisting are some of the more confusing topics in JavaScript. MDN has a good primer that’s worth checking out.
SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion