Mockando APIs REST com json-server
No dia a dia das empresas, é comum consumirmos APIs REST em nossos frontends. Eventualmente pode ser necessário desenvolvermos o frontend primeiro ou em paralelo, ao backend.
Quando isso acontece, temos de simular de alguma forma os dados enviados pelo backend, ou seja, dizemos que estamos trabalhando com mocks ou “mockando” o backend. Mock nada mais é que o nome dado para um conteúdo inventado e utilizado apenas como um marcador de posição.
Existem várias formas de se fazer isso. Uma delas, é pelo json-server. Resumidamente, o json-server vai simular uma API REST, com todos os endpoints de um recurso: GET, POST, PUT e DELETE. Assim, o nosso frontend consome essa API simulada, possibilitando a criação de toda a camada HTTP da aplicação.
O json-server é um pacote NPM que pode ser instalado globalmente em ambientes que possuam o Node.JS instalado. Então, nosso primeiro passo é executar a instalação:
npm install -g json-server
Feito isso, já podemos executar o comando json-server
no terminal, a partir de qualquer diretório:
Temos várias opções disponíveis para uso, mas vamos começar criando um arquivo JSON que representará o nosso backend. Vamos criar dois recursos:
- projetos;
- tarefas.
O projeto é uma entidade simples, que possui um nome e um ID numérico e incremental. A tarefa possui uma descrição, um ID numérico e um projeto. Assim, podemos representá-los:
{
"projetos": [
{
"id": 1,
"nome": "Alura Tracker 3.0"
},
{
"id": 2,
"nome": "ByteBank 2.0"
}
],
"tarefas": [
{
"id": 1,
"descricao": "Configuração do ambiente",
"projeto": {
"id": 1,
"nome": "Alura Tracker 3.0"
}
},
{
"descricao": "Refatoração do vuex 4",
"projeto": {
"id": 1,
"nome": "Alura Tracker 3.0"
},
"id": 2
}
]
}
Repare que se trata de uma estrutura JSON simples. Vamos salvar esse arquivo como db.json
. Temos um array com os projetos e outros com as tarefas, seguindo a estrutura definida anteriormente.
Agora, podemos executar o comando base:
json-server db.json
Acessando a rota de projetos:
Assim, o db.json
faz a coisa acontecer. Essas rotas são criadas a partir da estrutura do arquivo JSON. Logo, o que ocorre quando temos um array de tarefas e um de projetos? As duas rotas são criadas.
Inclusive, podemos ir além e criar um endpoint singular que vai retornar, por exemplo, os dados do usuário logado:
{
"projetos": [
{
"id": 1,
"nome": "Alura Tracker 3.0"
},
{
"id": 2,
"nome": "ByteBank 2.0"
}
],
"tarefas": [
{
"id": 1,
"descricao": "Configuração do ambiente",
"projeto": {
"id": 1,
"nome": "Alura Tracker 3.0"
}
},
{
"descricao": "Refatoração do vuex 4",
"projeto": {
"id": 1,
"nome": "Alura Tracker 3.0"
},
"id": 2
}
],
"usuario": {
"id": 13,
"nome": "Nathália Neves",
"perfil": "Administração"
}
}
Como alteramos o db.json
manualmente, temos que interromper o comando e iniciá-lo novamente para carregar as novas alterações. Sempre que o arquivo JSON for alterado, o ideal é que o json-server carregue automaticamente as novas informações. Então, vamos adicionar a opção --watch
:
json-server db.json –watch
Repare que, de acordo com a estrutura do JSON, o json-server monta os endpoints da APIs. Agora, temos as três rotas disponíveis e ainda mantemos o json-server observando alterações no arquivo db.json
.
Com o json-server rodando, podemos executar todas as operações em cada recurso. Usando o axios para fazer as requisições dos projetos, teríamos algo mais ou menos assim:
import axios from 'axios'
axios.get('http://localhost:3000/projetos')
.then(resposta => console.log(resposta.data))
axios.get('http://localhost:3000/projetos/1')
.then(resposta => console.log(resposta.data))
axios.post('http://localhost:3000/projetos', {
nome: 'Novo projeto incrivel'
})
.then(resposta => console.log(resposta.data))
axios.put('http://localhost:3000/projetos/1', {
id: 1,
nome: 'Novo projeto incrivel'
})
.then(resposta => console.log(resposta.data))
axios.delete('http://localhost:3000/projetos/1')
.then(resposta => console.log(resposta.data))
Temos várias outras funcionalidades, por exemplo, a de fazer uma busca utilizando uma propriedade específica:
import axios from 'axios'
axios.get('http://localhost:3000/projetos?nome=Alura Tracker 3.0')
.then(resposta => console.log(resposta.data))
Ou uma busca mais genérica, utilizando todos as propriedades disponíveis:
import axios from 'axios'
axios.get('http://localhost:3000/projetos?q=alura')
.then(resposta => console.log(resposta.data))
Tem muitas funcionalidades já prontas para uso, por exemplo, paginação:
import axios from 'axios'
axios.get('http://localhost:3000/projetos?_page=1&_limit=20)
.then(resposta => console.log(resposta.data))
Agora, com um ótimo backend emulado, estamos prontos para seguir com o desenvolvimento do frontend até que a verdadeira API esteja disponível!
O json-server
é uma ótima ferramenta para estar no cinto de utilidades de todas as pessoas desenvolvedoras. Se você quiser desvendar todo o potencial desse pacote, pode conferir a documentação completa aqui.
Vale ressaltar que, por baixo dos panos, o json-server
usa o lowdb para escrever as alterações direto no arquivo JSON.
Nos objetos dentro do arquivo JSON que representa os nossos recursos, a propriedade id
é imutável. Nós não conseguimos mudá-la fazendo PUT
ou PATCH
. Via de regra, não adianta passar a id
no corpo da requisição, pois ela será ignorada.
Embora o axios faça isso por padrão, é mandatório o envio do header Content-Type: application/json
para que as requisições sejam processadas corretamente caso as requisições HTTP sejam realizadas de outra forma.
Se você quer mergulhar ainda mais profundo do lado do backend, você pode aprender como construir APIs REST utilizando NodeJS, por exemplo. Agora, se o frontend é mais a sua praia, aqui você vai conhecer uma alternativa ao axios para fazer requisições web.