Construindo um Backend GraphQL sem uma Linha de Código

Lucas Santos - Apr 23 '20 - - Dev Community

Photo por Kevin Ku no Unsplash

Criar um backend simples não é uma tarefa tão simples assim... Ainda mais se quisermos que ele use tecnologias mais avançadas como o GraphQL.

Recentemente me encontrei em uma situação ao mesmo tempo simples, porém complexa. Eu estou precisando refazer o meu site pessoal, que hoje é apenas uma página template do GitHub websites, para meu novo site eu tenho certeza que gostaria de ter um arquivo de posts e atividades que participei, ou seja, quero ter uma lista de tudo que fiz e produzi para que possa colocar como um "portfolio" e também um guia para quem precisar acessar o site.

Como já estou planejando este desenvolvimento há um tempo, me inspirei no site do Erick Wendel para ter algumas ideias e decidi ter um backend em GraphQL por alguns motivos bem simples:

  • Não vou precisar usar todos os campos no site, portanto quero poder filtrar o que eu vou trazer da API
  • Quero ter a capacidade de descrever todo o Schema da minha API em um arquivo

Além disso, quero manter o site simples, não estou querendo nada super complicado ou evoluído, quanto menos tempo e menos código eu puder desprender nele, melhor!

A busca de ferramentas

Inicialmente me senti tentado a seguir para o Hasura, uma ferramenta excelente que provisiona backends em GraphQL instantaneamente, porém o problema é que o único banco suportado é o PostgreSQL, e eu realmente não queria utilizar um banco relacional para poder ter mais flexibilidade na hora de planejar o meu Schema.

Então, depois de alguma busca, acabei encontrando o Mongoke, uma ferramenta open-source que me permite fazer mais ou menos a mesma coisa, porém com o MongoDB.

Preparação

Para esse backend eu precisava de pelo menos um banco de dados já pronto. Então utilizei o Free Tier do MongoDB Atlas na Azure para poder ter um banco robusto sem precisar pagar nada.

Fora isso, todo o resto eu já tinha pronto:

  • Website no Github Pages (link)

Desenvolvimento

O Mongoke funciona da seguinte maneira:

  • Criamos um arquivo mongoke.yml com a descrição do nosso Schema GraphQL
  • Ao executar o Mongoke passando a string de conexão e o caminho do arquivo – ou a URL – teremos a criação de um webserver que servirá nossa API com queries prontas baseadas em nosso schema

Simples não? Vamos colocar em prática!

Criando o arquivo YML

A primeira coisa que precisamos fazer é criar o nosso arquivo de Schema do GraphQL. No meu banco de dados tenho uma collection chamada activities e ela possui alguns campos que vamos descrever no Schema do Mongoke:

# https://github.com/khaosdoctor/site-backend/raw/master/mongoke.yml
schema: |
  enum ActivityType {
    talk
    article
    foss
    other
    host
    book
    event
    podcast
    video
  }

  type Activity {
    _id: ObjectId
    id: Int
    date: Date
    title: String
    description: String
    type: ActivityType
    categories: String
    videos: String
    url: String
  }

types:
  Activity:
    collection: activities
Enter fullscreen mode Exit fullscreen mode

Primeiramente criamos um enum para descrever todos os tipos de atividades que tenho em meu banco de dados, isto vai ser essencial para podermos filtrar e validar os inputs do site quando ele estiver no ar.

Em seguida criamos um tipo Activity que será o registro propriamente dito. Este registro possui os campos descritos no schema anterior. Agora você deve estar se perguntando porque criamos apenas o registro único, não deveríamos ter criado um registro do tipo "lista de atividades"? Algo assim:

type ActivityList {
  data: [Activity]
}
Enter fullscreen mode Exit fullscreen mode

É ai que entra a mágica! O Mongoke automaticamente vai criar para nós um tipo <type>Nodes – no nosso caso, ActivityNodes – que segue a modelagem de nós e arestas tão comum do GraphQL, desta forma podemos ter a lista de atividades automaticamente.

Depois de definir o type, vamos precisar dizer que ele é relativo a uma collection no nosso banco, e é para isto que a seção types serve. Ela está basicamente dizendo que o tipo Activity está relacionado à collection activities no meu MongoDB.

Testando localmente

O Mongoke é completamente baseado em Docker, portanto vamos criar um arquivo docker-compose.yml para poder testar nosso setup localmente antes de precisar fazer o deploy!

# https://github.com/khaosdoctor/site-backend/raw/master/docker-compose.yml
version: "3"

services:
  backend:
    ports:
      - 80:80
    image: mongoke/mongoke
    environment:
      DB_URL: mongodb://mongo/contributions
      PORT: "80"
    volumes:
      - ./mongoke.yml:/conf.yml
  mongo:
    image: mvertes/alpine-mongo
    ports:
      - 27017:27017
Enter fullscreen mode Exit fullscreen mode

Veja que estamos subindo uma instancia do mongo localmente para testar e estamos usando as variáveis DB_URL e criando um volume local na raiz da imagem mongoke/mongoke para passar o nosso arquivo de schema. Estamos também liberando a porta 80 para acessar o nosso ambiente de testes GraphiQL:

Dica: Sempre use imagens alpine como o alpine-mongo porque elas tem um tamanho consideravelmente menor do que imagens normais

Colocando no ar

Para colocar o backend no ar eu também não queria nenhum tipo de trabalho extra, por isso eu utilizei as Azure Container Instances, que permitem que eu crie um container e rode ele de forma Serverless, ou seja, não tenho que me preocupar com escalabilidade e nem com máquinas, é só executar o meu container diretamente na nuvem!

E tudo fica muito mais simples porque já temos uma imagem pronta do mongoke/mongoke, ou seja, não vamos precisar fazer absolutamente nada de novo, só usar o que já está providenciado!

Para começar, vamos criar um novo resource group usando o Azure CLI.

Se você ainda não instalou e configurou seu CLI da Azure veja este link

Para fazer isso vamos simplesmente executar o seguinte comando:

az group create --name personal-website --location brazilsouth
Enter fullscreen mode Exit fullscreen mode

Dica: Você pode escolher outras regiões para colocar o seu grupo! Escolhi a região brasileira porque está geograficamente mais próxima da gente.

Depois disso, vamos criar a nossa instância do ACI através do comando:

az container create \
--resource-group personal-website \
--name personal-website-backend \
--image mongoke/mongoke \
--location brazilsouth \
--dns-name-label lsantos-api \
--ports 80 \
--environment-variables \
MONGOKE_CONFIG_URL="https://lsantos.me/site-backend/mongoke.yml" \
DB_URL="<sua URL de conexão com o Mongo Atlas>" \
DISABLE_GRAPHIQL="true"
Enter fullscreen mode Exit fullscreen mode

Perceba o seguinte. Como estamos executando nosso container de forma remote, eu não gostaria de ter que criar e mandar um arquivo para dentro do container, felizmente o Mongoke tem a possibilidade de colocarmos uma URL para o nosso arquivo Schema lá no github! Então podemos hospedar o nosso arquivo no Github Pages ou então pegar o endereço do arquivo raw e colocar na variável MONGOKE_CONFIG_URL.

Além disso também estou desativando o ambiente GraphiQL porque não queremos o ambiente de testes e sandbox funcionando em nosso ambiente de produção, não é mesmo?

Uma vez que executamos o comando, esperamos alguns instantes e poderemos ver nosso container criado no painel da Azure:

E poderemos acessar a instância, e até mesmo se conectar a ela e buscar seus logs através da aba Containers:

Podemos então acessar o domínio FQDN gerado pela Azure para poder ver nosso backend completamente no ar!

Conclusão e próximos passos

Este artigo foi baseado na Live que fiz com o Igor Halfeld sobre como podemos criar um backend em GraphQL, então se você quiser assistir como fazemos o desenvolvimento completo é só ver o vídeo abaixo!

O repositório deste backend:

GitHub logo khaosdoctor / site-backend

GraphQL Backend for my website

Para os próximos passos podemos aplicar uma série de automações, por exemplo:

  • Deploy automático via Github Actions diretamente para o ACI
  • Inserir um novo artigo no banco sempre que eu criar um novo artigo aqui no Dev.to
  • Inclusão do nosso FQDN direto em meu sub-domínio através do CloudFlare

E muitas outras ideias! O objetivo deste artigo é mostrar que não é necessário pagar horrores ou então ter um grande trabalho para criar um backend completo utilizando tecnologias de ponta como o GraphQL, você pode criar uma conta gratuitamente na Azure e usufruir dos créditos iniciais para fazer seus testes e até mesmo criar seu backend completo sem precisar pagar um centavo!

Não deixe de acompanhar mais do meu conteúdo no meu blog e se inscreva na newsletter para receber notícias semanais!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .