Construyendo una API con funciones de Gatsby
Publicado: 2022-03-10Probablemente haya oído hablar de las funciones sin servidor, pero si no lo ha hecho, las funciones sin servidor brindan una funcionalidad típicamente asociada con las tecnologías del lado del servidor que se pueden implementar junto con el código front-end sin quedar atrapado en las infraestructuras del lado del servidor.
Con el código del lado del servidor y del lado del cliente coexistiendo en la misma base de código, los desarrolladores front-end como yo podemos ampliar el alcance de lo que es posible utilizando las herramientas que ya conocen y aman.
Limitaciones
La coexistencia es excelente, pero hay al menos dos escenarios con los que me he encontrado en los que el uso de funciones sin servidor de esta manera no era el adecuado para la tarea en cuestión. Son los siguientes:
- El front-end no podía admitir funciones sin servidor.
- La misma funcionalidad fue requerida por más de un front-end.
Para ayudar a proporcionar algo de contexto, aquí hay un ejemplo de los puntos 1 y 2 mencionados anteriormente. Mantengo un proyecto de código abierto llamado MDX Embed, verá en el sitio de documentos que no es un sitio web de Gatsby. Se ha creado utilizando Storybook y Storybook por sí solo y no proporciona capacidades de función sin servidor. Quería implementar contribuciones de "Paga lo que quieras" para ayudar a financiar este proyecto y quería usar Stripe para permitir pagos seguros, pero sin un "backend" seguro. Esto no hubiera sido posible.
Al abstraer esta funcionalidad en una API creada con Gatsby Functions, pude lograr lo que quería con MDX Embed y también reutilizar la misma funcionalidad y habilitar la funcionalidad "Paga lo que quieras" para mi blog.
Puede leer más sobre cómo lo hice aquí: Monetice el software de código abierto con las funciones de Gatsby y Stripe.
Es en este punto que el uso de Gatsby Functions puede actuar como una especie de Back-end para front-end o BFF y desarrollar de esta manera es más parecido a desarrollar una API ( Interfaz de programación de aplicaciones ).
El código front-end utiliza las API para manejar cosas como inicios de sesión, obtención de datos en tiempo real o tareas seguras que no son manejadas adecuadamente por el navegador por sí solo. En este tutorial, explicaré cómo crear una API con Gatsby Functions e implementarla en Gatsby Cloud.
Comprobaciones previas al vuelo
Las funciones de Gatsby funcionan cuando se implementan en Gatsby Cloud o Netlify, y en este tutorial, explicaré cómo implementar en Gatsby Cloud, por lo que primero deberá registrarse y crear una cuenta gratuita.
También necesitará una cuenta de GitHub, GitLab o BitBucket, así es como Gatsby Cloud lee su código y luego construye su "sitio", o en este caso, API.
Para los propósitos de este tutorial, usaré GitHub. Si prefiere avanzar, puede encontrar el código API de demostración terminado en mi GitHub.
Empezando
Cree un nuevo directorio en algún lugar de su disco local y ejecute lo siguiente en su terminal. Esto configurará un package.json
predeterminado.json.
npm init -y
dependencias
Escriba lo siguiente en su terminal para instalar las dependencias requeridas.
npm install gatsby react react-dom
Paginas
Es probable que su API no tenga "páginas", pero para evitar ver la advertencia de página faltante predeterminada de Gatsby cuando visite la URL raíz en el navegador, agregue lo siguiente a src/pages/index.js
y src/pages/404.js
.
//src/pages/index.js & src/pages/404.js export default () => null;
API
Agregue lo siguiente a src/api/my-first-function.js
.
Explicaré un poco más adelante qué significa 'Access-Control-Allow-Origin', '*'
, pero en resumen, se asegura de que CORS no bloquee sus API de otros orígenes.
//src/api/my-first-function.js export default function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.status(200).json({ message: 'A ok!' }); }
Guiones
Agregue lo siguiente a package.json
.
//package.json ... "scripts": { "develop": "gatsby develop", "build": "gatsby build" }, ...
Inicie el servidor de desarrollo de Gatsby
Para activar el servidor de desarrollo de Gatsby, ejecute lo siguiente en su terminal.
npm run develop
Hacer una solicitud desde el navegador
Con el servidor de desarrollo de Gatsby en ejecución, puede visitar http://localhost:8000/api/my-first-function, y dado que se trata de una simple solicitud GET
, debería ver lo siguiente en su navegador.
{ "message": "A ok!" }
Felicidades
Acabas de desarrollar una API utilizando Gatsby Functions.
Desplegar
Si ve la respuesta anterior en su navegador, es seguro asumir que su función funciona correctamente localmente. En los siguientes pasos, explicaré cómo implementar su API en Gatsby Cloud y acceder a ella mediante una solicitud HTTP
de CodeSandbox.
Empuje el código a Git
Antes de intentar implementar en Gatsby Cloud, deberá enviar su código al proveedor de Git de su elección.
Nube Gatsby
Inicie sesión en su cuenta de Gatsby Cloud y busque el gran botón morado que dice "Agregar sitio +".
En el siguiente paso, se le pedirá que importe desde un repositorio de Git o que comience desde una plantilla, seleccione Import from Git Repository
y presione next
.
Como se mencionó anteriormente, Gatsby Cloud puede conectarse a GitHub, GitLab o Bitbucket. Seleccione su proveedor de Git preferido y presione next
.
Con su proveedor de Git conectado, puede buscar su repositorio y darle un nombre a su sitio.
Una vez que haya seleccionado su repositorio y nombrado su sitio, presione next
.
Puede omitir las "Integraciones" y la "Configuración", ya que no las necesitaremos.
Si todo ha ido según lo planeado, debería ver algo similar a la siguiente captura de pantalla.
Verá cerca de la parte superior en el lado izquierdo de la pantalla una URL que termina con gatsbyjs.io
, esta será la URL para su API y se puede acceder a cualquier función que cree agregando /api/name-of-function
el final de esta URL.
Por ejemplo, la versión completa implementada de my-first-function.js
para mi API de demostración es la siguiente:
API de demostración: mi primera función .
Prueba de su API
Visitar la URL de su API es una cosa, pero no es realmente cómo se usan normalmente las API. Idealmente, para probar su API, debe realizar una solicitud a la función desde un origen completamente no relacionado.
Es aquí donde res.setHeader('Access-Control-Allow-Origin', '*');
viene al rescate. Si bien no siempre es deseable permitir que cualquier dominio (sitio web) acceda a sus funciones, en su mayor parte, las funciones públicas son solo eso, públicas. Establecer el encabezado de Control de acceso en un valor de *
significa que cualquier dominio puede acceder a su función, sin esto, CORS bloqueará cualquier dominio que no sea el dominio en el que está alojada la API.
Aquí hay un CodeSandbox que usa my-first-function
de mi API de demostración. Puede bifurcar esto y cambiar la URL de solicitud de Axios para probar su función.
CodeSandbox: mi primera función
cada vez más elegante
Enviando una respuesta desde su API que dice message: "A ok!"
no es exactamente emocionante, así que a continuación le mostraré cómo consultar la API REST de GitHub y crear una tarjeta de perfil personal para mostrar en su propio sitio usando la API que acaba de crear, y se verá un poco como esto .
CodeSandbox: tarjeta de perfil de demostración
dependencias
Para usar la API REST de GitHub, deberá instalar el paquete @octokit/rest.
npm install @octokit/rest
Obtener usuario de GitHub sin formato
Agregue lo siguiente a src/api/get-github-user-raw.js
.
// src/api/get-github-user-raw.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: data }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
Ficha de acceso
Para comunicarse con la API REST de GitHub, necesitará un token de acceso. Puede obtener esto siguiendo los pasos de esta guía de GitHub: Creación de un token de acceso personal.
Variables .env
Para mantener su token de acceso seguro, agregue lo siguiente a .env.development
y .env.production
.
OCTOKIT_PERSONAL_ACCESS_TOKEN=123YourAccessTokenABC
Puede leer más sobre las variables de entorno de Gatsby en esta guía de Gatsby: Variables de entorno.
Iniciar servidor de desarrollo
Como lo hizo antes, inicie el servidor de desarrollo de Gatsby escribiendo lo siguiente en su terminal.
npm run develop
Hacer una solicitud desde el navegador
Con el servidor de desarrollo de Gatsby ejecutándose, puede visitar http://localhost:8000/api/get-github-user-raw, y dado que esto también es una solicitud GET
simple, debería ver lo siguiente en su navegador. ( He eliminado parte de la respuesta por brevedad).
{ "message": "A ok!", "user": { "login": "PaulieScanlon", "id": 1465706, "node_id": "MDQ6VXNlcjE0NjU3MDY=", "avatar_url": "https://avatars.githubusercontent.com/u/1465706?v=4", "gravatar_id": "", "url": "https://api.github.com/users/PaulieScanlon", "type": "User", "site_admin": false, "name": "Paul Scanlon", "company": "Paulie Scanlon Ltd.", "blog": "https://www.paulie.dev", "location": "Worthing", "email": "[email protected]", "hireable": true, "bio": "Jamstack Developer / Technical Content Writer (freelance)", "twitter_username": "pauliescanlon", "created_at": "2012-02-23T13:43:26Z", "two_factor_authentication": true, ... } }
Aquí hay un ejemplo de CodeSandbox de la respuesta sin procesar completa.
CodeSandbox: respuesta sin procesar
Verá en lo anterior que hay una gran cantidad de datos devueltos que realmente no necesito, lo siguiente depende completamente de usted, ya que es su API, pero me ha resultado útil manipular un poco la respuesta de la API de GitHub. antes de enviarlo de vuelta a mi código frontend.
Si desea hacer lo mismo, puede crear una nueva función y agregar lo siguiente a src/api/get-github-user.js
.
// src/api/get-github-user.js import { Octokit } from '@octokit/rest'; const octokit = new Octokit({ auth: process.env.OCTOKIT_PERSONAL_ACCESS_TOKEN }); export default async function handler(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); try { const { data } = await octokit.request(`GET /users/{username}`, { username: 'PaulieScanlon' }); res.status(200).json({ message: 'A ok!', user: { name: data.name, blog_url: data.blog, bio: data.bio, photo: data.avatar_url, githubUsername: `@${data.login}`, githubUrl: data.html_url, twitterUsername: `@${data.twitter_username}`, twitterUrl: `https://twitter.com/${data.twitter_username}` } }); } catch (error) { res.status(500).json({ message: 'Error!' }); } }
Verá en lo anterior que, en lugar de devolver el objeto de datos completo devuelto por la API REST de GitHub, selecciono solo los bits que necesito, les cambio el nombre y agrego algunos bits antes de los valores de nombre de usuario y URL. Esto hace que la vida sea un poco más fácil cuando se trata de representar los datos en el código de la interfaz.
Aquí hay un ejemplo de CodeSandbox de la respuesta formateada.
CodeSandbox: respuesta formateada
Esto es muy similar al CodeSandbox de tarjeta de perfil de antes, pero también imprimí los datos para que pueda ver cómo se usa cada elemento de datos manipulado.
Vale la pena señalar en este punto que las cuatro demostraciones de CodeSandbox en este tutorial usan la API de demostración, y ninguna de ellas está construida con Gatsby o alojada en Gatsby Cloud. ¡Genial, ay!
Variables .env
en Gatsby Cloud
Antes de implementar sus dos nuevas funciones, deberá agregar el token de GitHub Access a la sección de variables de entorno en Gatsby Cloud.
¿A dónde ir desde aquí?
Me hice esta misma pregunta. Por lo general, las funciones sin servidor se usan en solicitudes del lado del cliente y, aunque está bien, me preguntaba si también podrían usarse en el momento de la compilación para "hornear" datos de forma estática en una página en lugar de depender de JavaScript, que puede o no estar deshabilitado en el usuario. navegador.
…así que eso es exactamente lo que hice.
Este es un tipo de tablero de datos que utiliza los datos devueltos por Gatsby Functions tanto en tiempo de ejecución como de compilación. Construí este sitio usando Astro y lo implementé Páginas de GitHub.
La razón por la que creo que este es un gran enfoque es porque puedo reutilizar la misma funcionalidad tanto en el servidor como en el navegador sin duplicar nada.
En esta compilación de Astro, llegué al mismo punto final expuesto por mi API para devolver datos que luego se integran en la página (excelente para SEO) o el navegador los obtiene en tiempo de ejecución (excelente para mostrar datos actualizados o actualizados al minuto) .
Tablero de datos
Los datos que se muestran a la izquierda del sitio se solicitan en el momento de la compilación y se integran en la página con Astro. Los datos a la derecha de la página se solicitan en tiempo de ejecución mediante una solicitud del lado del cliente. He usado puntos finales ligeramente diferentes expuestos por la API REST de GitHub para consultar diferentes cuentas de usuario de GitHub que crean las diferentes listas.
Todo lo que ves en este sitio es proporcionado por mi API más completa. Lo he llamado: Paulie API y lo uso para varios de mis sitios web.
API de Paulie
La API de Paulie, como la API de este tutorial, está construida con Gatsby, pero debido a que Gatsby puede actuar como un sitio y una API, la he usado para documentar cómo funcionan todas mis funciones y cada punto final tiene su propia página que se puede usar como una página interactiva. patio de recreo... siéntete libre de echar un vistazo alrededor.
Entonces, ahí lo tiene, una API de Gatsby Functions que puede ser utilizada por cualquier código del lado del cliente o del lado del servidor, desde cualquier sitio web creado con cualquier pila tecnológica.
Pruébalo y me interesaría mucho ver lo que construyes. Siéntete libre de compartir en los comentarios a continuación o ven a buscarme en Twitter: @PaulieScanlon.