Navigate back to the homepage

De REST a GraphQL con Apollo

Cristobal Aguirre
August 12th, 2019 · 11 min read
  • Repo

  • Demo

Introduccion

En este artículo voy a mostrarte como usar Apollo-Server para tomar un REST API y “traducirlo” en un nodo de GraphQL---que luego puedes integrar con el resto de tu schema y leerlo desde el cliente con Apollo-Client. Esto es muy útil si ya tienes un schema y quieres interactuar con APIs externas que no controlas, o si ya tienes un backend armado en Django por ejemplo y no quieres re-escribir todo solo para probar esta nueva tecnología que se ha puesto tan popular.

No voy a poder cubrir GraphQL desde 0 en este post o se alargaría mucho (y también es bastante nuevo para mí) pero hay muy buenos recursos para aprender en internet, probablemente partiendo por la documentación de Apollo mismo.

Para que el ejemplo esté completo, voy a implementar este servidor en una página estática creada con Gatsby para mostrarte como podrías hacer uso de este servidor. Lo mejor, es que vamos a usar las funciones serverless de netlify para servirlo junto al cliente, de manera que nunca vas a tener que preocuparte por armar infraestructura---y va a ser totalmente gratis!

Qué vamos a construir

Para los ansiosos, acá puedes ver lo que vamos a construir. Es el starter theme de blog oficial de gatsby (se ve familiar?), y le agregué una página que se conecta a una API abierta que encontré del gobierno que lista los regalos recibidos por funcionarios del gobierno según la ley de lobby (no tengo ninguna intención política con esto, solo necesitaba una API abierta y esta era más interesante que mostrar el dólar observado del día).

Dejé todo lo relacionado al blog en sí sin adulterar, porque recuerda que el foco acá es conectar la API externa. Si navegas a /donaciones, podrás ver una lista con los datos que vienen de la API, donde puedes cambiar el número de página (la API viene con paginación) para obtener más resultados. Si navegas a /.netlify/functions/graphql, puedes ver el schema de graphql que generamos, e interactuar con los datos—esta es una de las mayores ventajas de esta tecnología sobre REST!

Resumen

Si miras a la rápida este post, vas a ver que es muy largo y quizás te va a parecer muy complicado. La verdad es que no hay nada muy complejo acá, y la única complicación realmente viene de tener que manejar muchos archivos al mismo tiempo. Por eso voy a poner acá una especie de guía para que quede claro más adelante como se relacionan los archivos a las distintas funcionalidades que estamos armando. Todo lo que está acá es lo que haremos durante el resto del post, por lo que no va a hacer mucho sentido ahora---tómalo como referencia si te pierdes más adelante con qué archivo hace qué cosa o por qué está donde está. Notar que algunos aspectos de esta estructura vienen dados y no se pueden reemplazar (Gatsby) mientras que otros fueron los que elegí yo y puedes usar otro que te acomode (Apollo).

  • Gatsby: La base del app, cuenta principalmente con 3 grupos de archivos:
    • Archivos de configuración, que van en la raíz del proyecto (gatsby-config.js, gatsby-ssr.js y gatsby-browser.js).
    • Archivos de contenido, todos dentro de la carpeta content. Cuando quieres escribir un post, agregar un archivo .mdx (markdown + JSX) a la carpeta correspondiente y Gatsby lo convierte en una página.
    • Archivos de funcionalidad, dentro de src y repartidos entre components y pages (cada archivo acá se traduce en una página del sitio). También están los archivos propios del theme que estamos usando, y que podemos sobre-escribir (shadow) para cambiar aspectos como el layout.
  • Apollo: Usaremos Apollo en 2 formas: Apollo-Server para leer la API REST externa y servir un endpoint con un servidor de GraphQL, y Apollo-Client para acceder a estos datos dentro de la app.
    • Server: Dentro de la carpeta src/apollo/server están los módulos que determinan el funcionamiento del servidor---datasource.js maneja la conexión al API externo, mientras que resolvers.js junta todos los resolvers que determinarán como resolver los queries/mutations que le vamos a enviar desde el cliente. Finalmente, el servidor es inicializado en src/lambda/graphql.js, lo que es un poco confuso porque este archivo está 100% relacionado con los 2 anteriores, sin embargo tiene que estar acá para que Netlify lo reconozca como una función lambda y la construya.
    • Client: Para poder usar el cliente de Apollo en gatsby, lo voy a inicializar en src/apollo/client.js, para luego importarlo con desde gatsby-ssr.js y gatsby-browser.js y así el ApolloProvider estará disponible en todos mis componentes (notar que hago esto a través de la función de utilidad en src/apollo/wrap-root-element.js).

Empezamos

Levantar el sitio gatsby

Para empezar, crea un nuevo sitio de gatsby con los siguientes comandos. Si no tienes gatsby instalado, corre primero npm install -g gatsby.

1$
2$ gatsby new gatsby-rest-apollo https://github.com/gatsbyjs/gatsby-starter-blog-theme
3$ cd gatsby-rest-apollo
4$ yarn install
5$ gatsby develop

Notar que gatsby-rest-apollo es el nombre que yo le puse al proyecto, y tu puedes elegir lo que quieras.

Si ahora navegas en tu explorador a http://localhost:8000, vas a ver el sitio listo. Si lo único que estuvieramos haciendo es un blog nuevo, estás listo! Cada archivo markdown que incluyas en la carpeta content/posts/ va a ser convertido en una página e incluido de manera automática—así de fácil es. Adicionalmente, estos archivos son tipo mdx, lo que te permite incluir componentes de react directamente en markdown! Luego lo conectas a netlify (al final veremos como hacer esto), y cada vez que hagas git push origin master se va a construir/publicar con tus cambios.

Instalar paquetes

En esta aplicación usaremos varios paquetes externos, y además necesitamos cambiar algunos de los scripts que vienen por default del starter de gatsby. Reemplaza el package.json con lo siguiente:

1{
2 "name": "gatsby-rest-apollo-example",
3 "private": true,
4 "version": "0.0.1",
5 "scripts": {
6 "develop": "gatsby develop",
7 "start": "gatsby develop",
8 "start:app": "npm run develop",
9 "start:lambda": "netlify-lambda serve src/lambda",
10 "build": "gatsby build",
11 "build:app": "gatsby build",
12 "build:lambda": "netlify-lambda build src/lambda"
13 },
14 "dependencies": {
15 "@apollo/react-hooks": "^3.0.0",
16 "apollo-boost": "^0.4.4",
17 "apollo-datasource-rest": "^0.6.1",
18 "apollo-server-lambda": "^2.8.1",
19 "dotenv": "^8.0.0",
20 "gatsby": "^2.13.61",
21 "gatsby-cli": "^2.7.30",
22 "gatsby-theme-blog": "^1.0.2",
23 "graphql-tag": "^2.10.1",
24 "isomorphic-fetch": "^2.2.1",
25 "netlify-lambda": "^1.5.1",
26 "react": "^16.9.0",
27 "react-dom": "^16.9.0",
28 "styled-components": "^4.3.2"
29 }
30}

Y ahora anda a la terminal y corre yarn install. Corre gatsby develop de nuevo para confirmar que todo sigue en pie bien.

Construir el servidor de GraphQL

Para empezar, vamos a armar un servidor con Apollo-server. Como en este caso el objetivo es incorporar REST, vamos a usar Rest Data Source. El beneficio de usar esto en lugar de simplemente hacer los calls con fetch desde los resolvers va a ser que vamos a conseguir todos los beneficios adicionales que da apollo con caching, y va a ser más fácil integrar varios APIs distintos. El proceso va a consistir en:

  1. Construir un schema –> Qué forma tienen tus datos
  2. Construir el datasource –> Cómo van a interactuar los resolvers con el API REST
  3. Armar los resolvers –> Qué tiene que pasar con cada query o mutation.
Schema

Primero tenemos que entender qué datos tenemos. Voy a usar ésta API abierta del Gobierno de Chile, que, entre otras cosas, tiene un par de endpoints para ver las donaciones a funcionarios del gobierno. Ahí puedes ver que del endpoint principal de donations vas a recibir una lista con objetos, cada uno con información de la donación como receptor, cargo, etc. Entonces para empezar, crea un archivo en src/lambda/ llamado graphql.js. Acá vamos a hacer todo lo necesario para crear el servidor de apollo, y convertirlo en una función serverless que puede ser manejada por netlify.

Si estuvieramos armando un servidor que se levante por si solo (fuera de gatsby y netlify), en lugar de graphql.js, verías en la mayoría de los tutoriales que a este archivo lo llaman server.js o simplemente index.js, y lo ponen junto a los modulos con los resolvers y el schema.

Si fuiste a ver la documentación de la API que puse arriba, vas a ver la forma en la que vienen los datos de vuelta. El primer paso ahora es traducir esto en un schema de GrapQL:

1// src/lambda/graphql.js
2const { ApolloServer, gql } = require("apollo-server-lambda");
3
4const typeDefs = gql`
5 scalar DateTime
6
7 type Query {
8 donations(page: Int, donationId: Int): [Donation!]!
9 donation(donationId: Int!): DonationDetail!
10 }
11
12 type Donation {
13 id_donativo: Int!
14 nombres: String!
15 apellidos: String!
16 pais: String
17 cargo: String
18 ocasion: String
19 descripcion: String
20 fecha: DateTime
21 nombre_institucion: String
22 }
23
24 type DonationDetail {
25 donation: Donation!
26 donantes: [Donor!]!
27 }
28
29 type Donor {
30 id_donativo: Int!
31 nombre: String!
32 pais: String!
33 tipo: String!
34 giro: String
35 actividades: String
36 domicilio: String
37 representante_legal: String
38 naturaleza: String
39 directorio: String
40 }
41`;

Acá definimos todo el schema que estará disponible de manera pública: Un Donation que consiste en un objecto con información básica del receptor, un tipo DonationDetail que incluye al Donation y también una lista con sus Donors, y la definición de estos donantes. Este es un schema pequeño y puedo incluirlo acá sin mucho problema—si creciera mucho, podrías moverlo a su propio archivo llamado schema.graphql e importarlo con :

1const { importSchema } = require("graphql-import");
2const path = require("path");
3
4const typeDefs = importSchema(path.resolve("src/schema.graphql"));

Data Source

Luego, vamos a crear el datasource—un objeto que va a encapsular toda la lógica relacionada a nuestra interacción con la API externa. Crea un archivo llamado datasource.js en src/apollo/server/:

1// src/apollo/server/datasource.js
2const { RESTDataSource, HTTPCache } = require("apollo-datasource-rest");
3
4class LobbyAPI extends RESTDataSource {
5 constructor() {
6 super();
7 this.baseURL = "https://www.leylobby.gob.cl/api/v1/";
8 this.httpCache = new HTTPCache();
9 }
10
11 // funciones por definir
12}
13module.exports = { LobbyAPI };

Este modulo va a crear un nuevo objeto que llamamos LobbyAPI, que hereda de RESTDataSource de Apollo. En el constructor definimos la url base a donde se harán los requests. Finalmente, se define una función para cada uno de los queries que queremos hacer. Es muy importante que para cada query que definas en tus resolver, tengas un método correspondiente en este archivo, o el datasource no va a saber que hacer. Para entender bien estás funciones, lo mejor es ir en paralelo con los resolvers, así que veamos eso primero y luego volvemos.

Resolvers

Los resolvers van a ir en otro archivo, y van a interactuar directamente con las funciones definidas en el data source. Tenemos que crear un resolver para cada query definido en nuestro schema:

1donations(page: Int, donationId: Int): [Donation!]!
2 donation(donationId: Int!): DonationDetail!

Uno llamado donations que recibe 2 argumentos y devuelve una lista de objetos, y otro llamado donation que recibo un ID y devuelve un objeto. En esta guía voy a mostrar solamente el primer resolver, y el segundo es similar y está disponible en el repo.

Empecemos con un resolver para obtener la lista de donaciones, disponible en https://www.leylobby.gob.cl/api/v1/donations{?page}{?institucion}{?cargo_pasivo}. Nuestro resolver va a tener que recibir argumentos para el número de página, el ID de la institución y el ID del cargo pasivo. Omitamos este último por simplicidad, y nuestro resolver se vería así:

1// src/apollo/server/resolvers.js
2const resolvers = {
3 Query: {
4 donations: async (parent, args, { dataSources }) => {
5 const { page, institutionId } = args;
6 const donations = await dataSources.lobbyAPI.getAllDonations(
7 page,
8 institutionId
9 );
10 return donations;
11 }
12 }
13};
14
15module.exports = resolvers;

Los resolvers siempre reciben 4 argumentos: (parent, args, context, info), y en nuestro caso solo nos importan realmente 2: el contexto y los argumentos. Los argumentos van a ser las variables que le pasaremos a nuestro query, y que son convertidos en un objeto que podemos destructurar.

El contexto va a venir con el dataSource que definimos en el paso anterior, que nos va a dar acceso a la función (aún por definir) que finalmente va a ser la que emite el request al API externo. Esta función que estamos llamando, getAllDonations, tenemos que definirla en el datasource para que reciba 2 argumentos, y tiene que devolver un lista de donations con la forma que definimos en el schema del primer paso. Este círculo es sin duda la parte más complicada y frustrante del proceso, ya que hay que estar muy concentrado en que va donde y que no falte nada, y si algo sale mal es difícil de encontrar. Vamos entonces a definir la función que recogerá los datos de la API:

1// src/apollo/server/datasource.js
2const { RESTDataSource, HTTPCache } = require("apollo-datasource-rest");
3
4class LobbyAPI extends RESTDataSource {
5 constructor() {
6 super();
7 this.baseURL = "https://www.leylobby.gob.cl/api/v1/";
8 this.httpCache = new HTTPCache();
9 }
10
11 async getAllDonations(page, institutionId) {
12 const donations = await this.get("donativos/", {
13 page,
14 institutionId
15 });
16 return donations.data;
17 }
18}
19module.exports = { LobbyAPI };

Y listo! eso es todo lo que necesitamos, ya que armamos el schema de manera que la API devuelve un objeto que en el atributo data contiene los datos que queremos con exactamente la forma que definimos. La función consiste solamente en llamar al método get de la clase base (podría ser post para un mutation) y le pasamos 2 argumentos: el path (relativo al URL base que definimos previamente) donde hacer el request, y un objeto con los parámetros. También podríamos incluir headers, data, etc.

Para entenderlo bien, veamos como se vería en proceso completo. Si el cliente quiere ver una lista con los donations, abre el playground de graphql y ve en el schema que hay un query definido como donations(page: Int, donationId: Int): [Donation!]!, que recibe 2 argumentos, page y donationId y devuelve una lista de objetos llamados Donation. Si realiza un query como el siguiente:

1query {
2 donations(page: 16) {
3 nombres
4 apellidos
5 }
6}

Se gatilla el resolver, que lo único que hace es llamar al método getAllDonations que definimos en el datasource (y que recibe en el contexto) traspasando los argumentos que recibe. Finalmente, si vamos a esta función vemos que realiza un request GET al url https://www.leylobby.gob.cl/api/v1/ + donativos/, entregando adicionalmente estos 2 argumentos como parámetros del request (van al final como ?page=16&insitucion=null). Esta función recibe un objeto que guardamos en la constante donations y devuelve lo que está en el atributo data, que sabemos (mirando la documentación de la API externa) que es un objeto con la información que queremos. este objeto es traspasado directamente por el resolver (esta vez a través de la variable donations) y así llega finalmente al cliente, filtrando para entregar solamente los atributos requeridos por este: nombres y apellidos.

El otro resolver, para el query donation(id: Int!) tiene una forma similar y no lo voy a incluir acá por espacio, pero lo puedes ver en el repo. Esta API solamente va a realizar queries, ya que no tengo acceso a modificar datos que no son míos. Pero en un ejemplo más real donde estás interactuando totalmente con una base de datos, se pueden crear mutations con estos mismos pasos.

Con los resolvers listos, volvemos al archivo base graphql.js para incorporarlos y dar por terminado el servidor:

1// src/lambda/graphql.js
2const { ApolloServer, gql } = require("apollo-server-lambda");
3const { LobbyAPI } = require("../apollo/server/datasource");
4const resolvers = require("../apollo/server/resolvers");
5
6const typeDefs = gql`
7 scalar DateTime
8
9 type Query {
10 donations(page: Int, donationId: Int): [Donation!]!
11 donation(donationId: Int!): DonationDetail!
12 }
13
14 type Donation {
15 // ...
16 }
17
18 type DonationDetail {
19 // ...
20 }
21
22 type Donor {
23 // ...
24 }
25`;
26
27const server = new ApolloServer({
28 typeDefs,
29 resolvers,
30 dataSources: () => ({
31 lobbyAPI: new LobbyAPI()
32 })
33});
34
35// Exportar el servidor en una función del formato que netlify espera
36exports.handler = server.createHandler();

Por último, crea un archivo llamado netlify.toml en la raíz del proyecto con la configuración necesaria para que netlify sepa que hacer con esta función.

1[build]
2 command = "yarn build"
3 functions = "built-lambda"
4 publish = "public"

Con esto listo, podemos inicializar nuestro servidor en development y ver como funciona. Abre otra terminal, y corre NODE_ENV=development npm run start:lambda. Si navegas a localhost:9000/.netlify/functions/graphql, vas a ver el GraphQL Playground donde puedes interactuar con los queries que creaste. Pega este snippet para ver ejemplos de como funciona.

1query GET_DONATIONS {
2 donations(page: 1) {
3 nombres
4 apellidos
5 cargo
6 ocasion
7 descripcion
8 }
9}

Incorporar nuestra nueva API en el cliente

Con el servidor listo, vamos a conectarlo ahora con nuestro sitio gatsby usando Apollo-Client. Primero vamos a hacer los cambios necesarios en los archivos de configuración, y luego veremos como se puede acceder a esta data desde nuestros componentes. Este proceso es bastante estándar y los saqué casi literalmente de éste repositorio de Jason Lengstorf, que trabaja en Gatsby y tiene muy buen material para aprender.

Creando el cliente

Lo primero que hay que hacer es inicializar un nuevo cliente que se conecte a nuestro endpoint—lo haremos creando un archivo en src/apollo/ llamado client.js. El cliente va a apuntar al url en donde netlify engancha nuestro servidor.

1// src/apollo/client.js
2import ApolloClient from "apollo-boost";
3import fetch from "isomorphic-fetch";
4
5export const client = new ApolloClient({
6 uri: "/.netlify/functions/graphql",
7 fetch
8});

Luego tenemos que incluir el ApolloProvider que recibe este cliente en nuestra aplicación. Normalmente, este se pone como wrapper a un componente alto en la jerarquía, como App.js si usáramos create-react-app, pero en este caso vamos a tener que hacerlo distinto para que funcione con gatsby y el server side rendering. Para esto creamos un archivo llamado wrap-root-element.js, que hará justamente esto, y luego lo usaremos como el único export desde 2 archivos de configuración de gatsby: gatsby-ssr.js y gatsby-browser.js, que dictan el comportamiento de la app cuando está siendo ejecutada en el servidor y en el cliente, respectivamente. Estos archivos van en la raíz del proyecto, al mismo nivel que gatsby-config.js.

1// src/apollo/wrap-root-element.js
2import React from 'react'
3import { ApolloProvider } from '@apollo/react-hooks';
4import {client} from './client'
5
6export const wrapRootElement = ({ element }) => (
7 <ApolloProvider client={client}>
8 {element}
9 </ApolloProvider>
10 )
11
12
13// gatsby-browser.js
14export { wrapRootElement } from "./src/apollo/wrap-root-element";
15
16
17//gatsby-ssr.js
18export { wrapRootElement } from "./src/apollo/wrap-root-element";

Finalmente, para poder interactuar con el servidor en nuestra maquina local durante desarrollo, hay que crear una proxy desde donde se encuentra actualmente, localhost:9000, al dominio del cliente. Con este cambio, ahora vas a poder acceder al playground directamente desde http://localhost:8000/.netlify/functions/graphql. Abre gatsby-config.js e incluye lo siguiente:

1const proxy = require("http-proxy-middleware");
2
3module.exports = {
4 plugins: [
5 // .....
6 ],
7 siteMetadata: {
8 // ....
9 },
10 developMiddleware: app => {
11 app.use(
12 "/.netlify/functions/",
13 proxy({
14 target: "http://localhost:9000",
15 pathRewrite: {
16 "/.netlify/functions/": ""
17 }
18 })
19 );
20 }
21};

Incluyendo la data en nuestro componentes

Con esto, finalmente podemos acceder a nuestra data usando los métodos que provee Apollo. A modo de ejemplo, voy a crear una página en /donaciones que va a cargar una lista con donaciones y mostrarla como tabla. Primero creamos esta página, creando el archivo donaciones.js en src/pages/.

1// src/pages/donaciones.js
2import React from "react";
3import Layout from "gatsby-theme-blog/src/components/layout";
4
5export default function donaciones() {
6 return (
7 <Layout location="/donaciones" title="Home">
8 <h2>Donaciones a funcionarios del gobierno</h2>
9 </Layout>
10 );
11}

Si vas a localhost:8000/donaciones, deberías ver esta página, prácticamente en blanco. Ahora creamos un componente ahora que reciba y muestre los datos en la consola.

1// src/components/getDonations.js
2import React from 'react'
3import gql from 'graphql-tag'
4import {useQuery} from '@apollo/react-hooks'
5
6const GET_DONATIONS = gql`
7query getDonations {
8 donations(page: 1) {
9 id_donativo
10 nombres
11 apellidos
12 cargo
13 ocasion
14 descripcion
15 fecha
16}}
17`
18
19export default function GetDonations() {
20 const { loading, error, data, refetch } = useQuery(GET_DONATIONS);
21
22 console.log(data)
23 return (
24 <div>Nothing here yet</div>
25 )

Ahora vuelve a donaciones.js e incluyelo.

1import React from "react";
2import Layout from "gatsby-theme-blog/src/components/layout";
3import GetDonations from "../components/getDonations";
4
5export default function donaciones() {
6 return (
7 <Layout location="/donaciones" title="Home">
8 <h2>Donaciones a funcionarios del gobierno</h2>
9 <GetDonations />
10 </Layout>
11 );
12}

Si haces refresh, deberías ver en la consola como se carga la data. Eso es todo! Ahora que tienes acceso a la data, puedes hacer lo que quieras. Para darle un poco más de interactividad a la cosa, incluyamos la posibilidad de cambiar el número de página a buscar, y mostremos la data en una tabla.

1import React, { useState } from "react";
2import gql from "graphql-tag";
3import styled from "styled-components";
4import { useQuery } from "@apollo/react-hooks";
5
6const GET_DONATIONS = gql`
7 query getDonations($page: Int) {
8 donations(page: $page) {
9 id_donativo
10 nombres
11 apellidos
12 cargo
13 ocasion
14 descripcion
15 fecha
16 }
17 }
18`;
19
20export default function GetDonations() {
21 const [page, setPage] = useState(1);
22 const { loading, error, data, refetch } = useQuery(GET_DONATIONS, {
23 variables: { page }
24 });
25
26 const handleChange = e => {
27 const newPage = parseInt(e.target.value);
28 setPage(newPage);
29 refetch({ newPage });
30 };
31
32 const renderTable = () => {
33 return data.donations.map(donation => (
34 <Tr key={donation.id_donativo}>
35 <Td>{donation.id_donativo}</Td>
36 <Td>{`${donation.nombres} ${donation.apellidos}`}</Td>
37 <Td>{donation.cargo}</Td>
38 <Td>{donation.ocasion}</Td>
39 <Td>{donation.descripcion}</Td>
40 <Td>{donation.fecha}</Td>
41 </Tr>
42 ));
43 };
44 return (
45 <div>
46 <div>
47 <input type="number" value={page} onChange={handleChange} />
48 </div>
49 <T>
50 <thead>
51 <Tr>
52 <Th>ID</Th>
53 <Th>Nombre receptor</Th>
54 <Th>Cargo</Th>
55 <Th>Ocasión</Th>
56 <Th>Descripción</Th>
57 <Th>Fecha</Th>
58 </Tr>
59 </thead>
60 <tbody>
61 {loading && (
62 <tr>
63 <td>Loading</td>
64 </tr>
65 )}
66 {data.donations && data.donations.length > 0 && renderTable()}
67 </tbody>
68 </T>
69 </div>
70 );
71}
72
73const T = styled.table`
74 width: 100%;
75 border-collapse: collapse;
76 color: #686f7a;
77 tbody:before {
78 content: "-";
79 display: block;
80 line-height: 0.6em;
81 color: transparent;
82 }
83`;
84
85const Th = styled.th`
86 text-align: "left";
87 font-size: 18px;
88 color: #686f7a;
89 font-weight: 700;
90 opacity: 0.65;
91`;
92
93const Td = styled.td`
94 text-align: "left";
95`;
96
97const Tr = styled.tr`
98 border-bottom: 2px solid rgba(150, 150, 150, 0.5);
99`;

Deployment a Netlify

Con la app lista, ahora solo queda subirla para que todo el mundo la vea! Netlify hace esto muy fácil, y totalmente gratis. Subir una página de gatsby a netlify está muy bien documentado así que no voy a repetirlo acá---y si hiciste los cambios que mencioné antes en el package.json y netlify.toml, ya estás listo para seguir las guías estándar.

Una vez que hayas conectado tu cuenta de github a netlify, cada vez que hagas un push a master, netlify va a reconstruir tu aplicación y servirla vía sus CDNs.

Conclusión

Bueno, eso fue bastante más largo de lo que me imaginé que iba a ser—y aún así siento que tuve que pasar cosas por encima! Espero que te sirva para tener una idea de lo que se puede hacer con las herramientas disponibles hoy en día. Si seguiste todos los pasos en este post, creaste una aplicación usando el famoso JAMStack—contenido dinámico e interfaces inteligentes, sin bases de datos, sin maquinas virtuales, sin load balancers, sin servidores—pero con todos los beneficios de server-side rendering como SEO y performance.

Para otro post me gustaría mostrar una versión alternativa de lo que hicimos acá: he estado jugando com Prisma y Next.js y me ha encantado. Gatsby realmente reluce cuando el contenido de una app es principalmente estático (en el sentido que no necesita una base de datos para funcionar), como para un blog, restaurant, incluso e-commerce. Otro feature que me encanta de netlify es el CMS que provee, que se puede integrar con Gatsby si quieres hacer una página con contenido 100% editable por gente que jamás va a tener que tocar la terminal para usar git. Pero para aplicaciones más complejas, del tipo que se desarrollaría de manera especial para resolver problemas de negocio, ya se hace necesario interactuar con una base de datos y tener una aplicación más versátil. Next y Prisma permiten esto de una manera muy elegante, se puede conseguir sin mucho más código que el que usamos acá (la parte de Apollo es casi igual).

Como hay mucho que digerir en este post, habilité los comentarios por si hay algo que no funciona o te gustaría que profundice más.

More articles from Cristobal Aguirre

ML Part 3: Gradient Boosting

El último post de la serie, donde crearemos una máquina de Gradient Boosting desde 0 en Python

June 26th, 2019 · 5 min read

Scraping Twitter

Un programa sencillo escrito en Python para descarga información histórica de Twitter

June 4th, 2019 · 5 min read
© 2019 Cristobal Aguirre
Link to $https://twitter.com/jcaguirre89Link to $https://github.com/jcaguirre89