Artigo original: Building a Simple CRUD Application with Express and MongoDB

Escrito por: Zell Liew

Por muito tempo, não ousei me aventurar no desenvolvimento de back-end. Me sentia intimidado por causa da minha falta de formação acadêmica em programação.

Lembro-me de quando finalmente criei coragem para tentar o desenvolvimento de back-end. Tive tanta dificuldade em entender a documentação do Express, MongoDB e Node.js que desisti.

No fim, voltei e trabalhei para esclarecer minha confusão. Agora, um ano depois, entendi como trabalhar com essas ferramentas. Então, decidi escrever este tutorial abrangente para que você não precise passar pela mesma dor de cabeça que eu passei.

CRUD, Express e MongoDB

CRUD, Express e MongoDB são palavras grandes para uma pessoa que nunca tocou em programação do lado do servidor em sua vida. Vamos apresentar rapidamente o que elas são antes de mergulharmos no tutorial.

Express é um framework para construir aplicações para a web com base no Node.js. Ele simplifica o processo de criação do servidor que já está disponível no Node. Caso você esteja se perguntando: o Node permite que você use JavaScript como sua linguagem do lado do servidor.

MongoDB é um banco de dados. É no banco de dados que você armazena informações para seus sites (ou aplicações) para a web.

CRUD é uma abreviação em inglês para Criar, Ler, Atualizar e Excluir. É um conjunto de operações que fazemos para que os servidores as executem (POST, GET, PUT e DELETE, respectivamente). Isso é o que cada operação faz:

  • Criar (POST) — Criar algo
  • Ler (GET) — Obter algo
  • Atualizar (PUT) — Alterar algo
  • Excluir (DELETE)– Remover algo

Se colocarmos CRUD, Express e MongoDB juntos em um único diagrama, seria assim:

0_UKwrPtpRSGFiDomm
À direita, o navegador. Entre ele e o servidor, as operações de CRUD.

CRUD, Express e MongoDB fazem mais sentido para você agora?

Ótimo. Vamos em frente.

O que vamos construir

Vamos construir uma aplicação de lista simples que permite que você acompanhe as coisas dentro de uma lista (como uma Lista de Tarefas, por exemplo).

Bem, uma lista de tarefas é meio chata. Que tal fazermos uma lista de citações de personagens de Star Wars? Incrível, não é? Além disso, aqui é onde você pode encontrar o código finalizado para a aplicação.

A propósito, o que estamos construindo não é uma aplicação de página única atraente. Estamos focando principalmente em como usar o CRUD, o Express e Mongo DB neste tutorial. Serão, portanto, mais orientações de como criar o lado do servidor. Não vou enfatizar o estilo.

Você precisará de duas coisas para começar com este tutorial:

  1. Você não deve ter medo de digitar comandos em um shell. Confira este artigo (em inglês) se estiver com medo.
  2. Você precisa ter o Node instalado.

Para verificar se você tem o Node instalado, abra sua linha de comando e execute o seguinte código:

$ node -v

Você deve obter um número de versão se tiver o Node instalado. Se não tiver, você pode instalar o Node baixando o instalador do site do Node ou baixando-o por meio de gerenciadores de pacotes como Homebrew (Mac) e Chocolatey (Windows).

Começando

Comece criando uma pasta para este projeto. Sinta-se à vontade para chamá-la do que quiser. Depois de navegar até ela, execute o comando npm init.

Esse comando cria um arquivo package.json, que ajuda você a gerenciar as dependências que instalaremos mais tarde no tutorial.

$ npm init

Basta pressionar Enter em tudo o que aparecer. Falarei sobre o que você precisa saber à medida que avançamos.

Executando o Node pela primeira vez em sua vida

A maneira mais simples de usar o node é executar o comando node e especificar um caminho para um arquivo. Vamos criar um arquivo chamado server.js para executar o node.

$ touch server.js

Quando executarmos o arquivo server.js, queremos ter certeza de que ele está sendo executado corretamente. Para fazer isso, basta escrever uma instrução console.log no server.js:

console.log('Que o Node esteja com você')

Agora, execute node server.js em sua linha de comando e você deverá ver a instrução que você registrou:

0_82cfsJUuV4b0Mmn2
Se você enxergar May Node be with you (Que o Node esteja com você), é sinal de que deu certo.

Ótimo. Vamos em frente e aprender como usar o Express agora.

Usando o Express

Primeiro, temos que instalar o Express antes de podermos usá-lo em nossa aplicação. Instalar o Express é muito fácil. Tudo o que temos que fazer é executar um comando de instalação com o gerenciador de pacotes do Node (npm), que vem junto com o Node.

Execute o comando npm install express --save em sua linha de comando:

$ npm install express --save

Depois de terminar, você deverá ver que o npm salvou o Express como uma dependência no package.json.

0_WQ2iauA--9SEqja3
A versão da dependência será diferente, dependendo de quando você estiver lendo este artigo.

Em seguida, usamos o express em server.js exigindo-o.

const express = require('express');
const app = express();

A primeira coisa que queremos fazer é criar um servidor ao qual os navegadores possam se conectar. Podemos fazer isso com a ajuda de um método listen fornecido pelo Express:

app.listen(3000, function() {
	console.log('Escutando na porta 3000')
})

Agora, execute node server.js e navegue até localhost:3000 em seu navegador. Você deverá ver uma mensagem que diz Cannot get /.

0HuIZ1G3D7TMPjbdU

Isso é um bom sinal. Significa que agora podemos nos comunicar com nosso servidor do Express através do navegador. É aqui que começamos as operações CRUD.

CRUD — LER

A operação LER é realizada pelos navegadores sempre que você visita uma página da web. Nos bastidores, os navegadores enviam uma solicitação GET ao servidor para realizar uma operação de LEITURA. O motivo pelo qual vemos o erro "Cannot get /" é porque ainda não enviamos nada de volta ao navegador do nosso servidor.

No Express, lidamos com uma solicitação GET com o método get:

app.get(caminho, callback)

O primeiro argumento, caminho, é o caminho da solicitação GET. É qualquer coisa que vem depois do nome de domínio.

Quando estamos visitando localhost:3000, nossos navegadores estão, na verdade, procurando por localhost:3000/. O argumento caminho, neste caso, é /.

O segundo argumento é uma função de callback que informa ao servidor o que fazer quando o caminho é correspondido. Ele recebe dois argumentos, um objeto de solicitação e um objeto de resposta:

app.get('/', function (request, response) {
  // faça algo aqui
})

Por enquanto, vamos escrever "Olá Mundo" de volta para o navegador. Fazemos isso usando um método send que vem com o objeto de resposta:

app.get('/', function(req, res) {
  res.send('Olá Mundo')
}) // Observação: solicitação e resposta são geralmente escritas como req e res, respectivamente.

Vou começar a escrever em código ES6 e mostrar como converter para ES6 ao longo do caminho também. Primeiro, estou substituindo o function() pela arrow function, da ES6. O código abaixo é o mesmo que o código acima:

app.get('/', (req, res) => {
  res.send('Olá mundo')
})

Agora, reinicie seu servidor fazendo o seguinte:

  1. Pare o servidor atual pressionando CTRL + C na linha de comando.
  2. Execute node server.js novamente.

Em seguida, navegue até localhost:3000 em seu navegador. Você deverá ver uma string que diz "Hello World" (Olá Mundo).

0jBDbdhi2v2N82RvP

Ótimo. Vamos mudar nossa aplicação para que sirva uma página index.html de volta para o navegador. Para fazer isso, usamos o método sendFile que é fornecido pelo objeto res.

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html')
}) // Observação: __dirname é o caminho para o seu diretório de trabalho atual. Tente registrá-lo e veja o que você obtém! O meu era '/Users/zellwk/Projects/demo-repos/crud-express-mongo' para esta aplicação.

No método sendFile() acima, dissemos ao Express para servir um arquivo index.html que pode ser encontrado na raiz da pasta do seu projeto. Ainda não temos esse arquivo. Vamos criá-lo agora.

touch index.html

Vamos colocar algum texto em nosso arquivo index.html também:

<!DOCTYPE html>
<html lang="en">
	<head>
	  <meta charset="UTF-8">
	  <title>MEU APP</title></head>
	</head>
	<body>
		Que o Node e o Express estejam com você.
	</body>
</html>

Reinicie seu servidor e atualize seu navegador. Você deverá ver os resultados do seu arquivo HTML agora.

0_oisDzT819Ex3FtDs
Você deve ver May Node and Express be with you/Que o Node e o Express estejam com você!

É assim que o Express lida com uma solicitação GET (operação LER) em poucas palavras.

Neste ponto, você provavelmente percebeu que precisa reiniciar seu servidor sempre que fizer uma alteração em server.js. Esse processo é incrivelmente tedioso. Por isso, vamos fazer um pequeno desvio e otimizá-lo usando um pacote chamado nodemon.

Apresentando o Nodemon

O Nodemon reinicia o servidor automaticamente sempre que você salva um arquivo que o servidor usa. Podemos instalar o Nodemon usando o seguinte comando:

$ npm install nodemon --save-dev

Observação: o motivo pelo qual estamos usando uma flag --save-dev aqui é porque estamos usando o Nodemon apenas quando estamos desenvolvendo. Essa flag salvaria o Nodemon como uma devDependency em seu arquivo package.json.

Continuando, o Nodemon se comporta exatamente da mesma maneira que o node, o que significa que podemos executar nosso servidor chamando nodemon server.js. No entanto, não podemos fazer isso na linha de comando agora porque o Nodemon não está instalado com uma flag -g.

Há outra maneira de executar o Nodemon — podemos executá-lo a partir da pasta node_modules. O código se parece com isto:

$ ./node_modules/.bin/nodemon server.js

Isso é muito para digitar. Uma maneira de simplificar é criar uma chave de script em package.json.

{  
	// ...
   "scripts": {
		"dev": "nodemon server.js"
	}
    // ...
}

Agora, você pode executar npm run dev para acionar nodemon server.js.

De volta ao tópico principal. Vamos cobrir a operação CRIAR em seguida.

CRUD — CRIAR

A operação CRIAR é realizada apenas pelo navegador se uma solicitação POST for enviada ao servidor. Essa solicitação POST pode ser acionada com JavaScript ou por meio de um elemento <form>.

Vamos descobrir como usar um elemento <form> para criar entradas para nossa aplicação de citações de Star Wars para esta parte do tutorial.

Para fazer isso, você primeiro precisa criar um elemento <form> e adicioná-lo ao seu arquivo index.html. Você precisa ter três coisas nesse elemento de formulário:

  1. Um atributo action
  2. Um atributo method
  3. Atributos name em todos os elementos <input> dentro do formulário
<form action="/quotes" method="POST">
	<input type="text" placeholder="nome" name="nome">
	<input type="text" placeholder="citação" name="citação">
	<button type="submit">Enviar</button>
</form>

O atributo action informa ao navegador para onde navegar em nossa aplicação Express. Neste caso, estamos navegando para /quotes. O atributo method informa ao navegador qual solicitação enviar. Neste caso, é uma solicitação POST.

Em nosso servidor, podemos lidar com essa solicitação POST com um método post que o Express fornece. Ele recebe os mesmos argumentos que o método GET:

app.post('/quotes', (req, res) => {  console.log('Oláááááááááááááá!')})

Reinicie seu servidor (espero que você tenha configurado o Nodemon para que ele reinicie automaticamente) e atualize seu navegador. Em seguida, insira algo em seu elemento de formulário. Você deverá ver Oláááááááááááááá! em sua linha de comando.

0_qsLmf8vEhBlhIfJj
Você deverá ver Helloooooooooooooooo! ou Oláááááááááá

Ótimo, sabemos que o Express está lidando com o formulário para nós agora. A próxima pergunta é: como obtemos os valores de entrada com o Express?

Acontece que o Express não lida com a leitura de dados do elemento <form> por conta própria. Temos que adicionar outro pacote chamado body-parser para obter essa funcionalidade.

$ npm install body-parser --save

O Express nos permite adicionar middlewares como body-parser à nossa aplicação com o método use. Você ouvirá muito o termo middleware ao lidar com o Express. Essas coisas são basicamente plug-ins que alteram o objeto de solicitação ou resposta antes que eles sejam tratados por nossa aplicação. Certifique-se de colocar o body-parser antes de seus manipuladores CRUD!

const express = require('express')
const bodyParser= require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended: true}))
// Todos os outros manipuladores aqui...

O método urlencoded dentro do body-parser informa ao body-parser para extrair dados do elemento <form> e adicioná-los à propriedade body no objeto de solicitação.

Nota da tradução: nas versões mais recentes, é possível usar express.json no lugar de body-parser para fazer o parsing do documento, tornando desnecessária a requisição deste último.

Agora, você deverá ver tudo no campo do formulário dentro do objeto req.body. Tente fazer um console.log e veja o que é!

app.post('/quotes', (req, res) => {
  console.log(req.body)
})

Você deverá obter um objeto semelhante ao seguinte em sua linha de comando:

0_cmNU6GQhNS7BYsLT

Hmmm. Mestre Yoda falou! Vamos garantir que nos lembremos das palavras de Yoda. É importante. Queremos poder recuperá-las na próxima vez que carregarmos nossa página inicial.

É aqui que entra o banco de dados, o MongoDB.

MongoDB

Primeiro, temos que instalar o MongoDB através do npm se quisermos usá-lo como nosso banco de dados.

npm install mongodb --save

Depois de instalado, podemos nos conectar ao MongoDB através do método connect do Mongo.Client, conforme mostrado no código abaixo:

const MongoClient = require('mongodb').MongoClient
MongoClient.connect('link-para-o-mongodb', (err, database) => {
  // ... inicie o servidor
})

A próxima parte é obter o link correto para nosso banco de dados. A maioria das pessoas armazenam seus bancos de dados em serviços em nuvem como o MongoLab. Faremos o mesmo também.

Então, vá em frente e crie uma conta no MongoLab. (É grátis). Depois de terminar, crie uma nova implantação do MongoDB e defina o plano como sandbox.

0_YujCEhVovfSgPH_j

Depois de terminar de criar a implantação, vá até ela e crie um usuário de banco de dados e uma senha de banco de dados. Lembre-se do usuário e da senha do banco de dados porque você os usará para conectar o banco de dados que acabou de criar.

0_pPeHMc1EqlQRAqKU

Finalmente, pegue o URL do MongoDB e adicione-a ao seu método MongoClient.connect. Certifique-se de usar seu usuário e senha do banco de dados!

0_x5a1AplcCRyq712P
MongoClient.connect('seu-url-do-mongodb', (err, database) => {
  // ... faça algo aqui
})

Em seguida, queremos iniciar nossos servidores apenas quando o banco de dados estiver conectado. Portanto, vamos mover app.listen para dentro do método connect(). Também vamos criar uma variável db para nos permitir usar o banco de dados quando lidarmos com solicitações do navegador.

var db
MongoClient.connect('sua-url-do-mongodb', (err, database) => {
  if (err) return console.log(err)
  db = database  
  app.listen(3000, () => {
    console.log('escutando na porta 3000')
  })
})

Terminamos de configurar o MongoDB. Agora, vamos criar uma coleção de citações para armazenar citações para nossa aplicação.

A propósito, uma coleção é um local nomeado para armazenar coisas. Você pode criar quantas coleções quiser. Podem ser coisas como "produtos", "citações", "mantimentos" ou quaisquer outros rótulos que você escolher.

Podemos criar a coleção de citações usando a string quotes ao chamar o método db.collection() do MongoDB. Ao criar a coleção de citações, também podemos salvar nossa primeira entrada no MongoDB com o método save simultaneamente.

Depois de terminarmos de salvar, temos que redirecionar o usuário para algum lugar (ou ele ficará preso esperando para sempre que nosso servidor se mova). Nesse caso, vamos redirecioná-los de volta para /, o que faz com que seus navegadores recarreguem.

app.post('/quotes', (req, res) => {
  db.collection('quotes').save(req.body, (err, result) => {
    if (err) return console.log(err)
    console.log('salvo no banco de dados')
    res.redirect('/')
    })
})

Agora, se você inserir algo no elemento, poderá ver uma entrada em sua coleção do MongoDB.

0_XEGKefxWJP6SlQpM

Uhuuu! Já que já temos algumas citações na coleção, por que não tentar mostrá-las ao nosso usuário quando ele acessar nossa página?

Mostrando citações aos usuários

Temos que fazer duas coisas para mostrar as citações armazenadas no MongoLab aos nossos usuários.

  1. Obter citações do MongoLab
  2. Usar um mecanismo de template para exibir as citações

Vamos passo a passo.

Podemos obter as citações do MongoLab usando o método find que está disponível no método collection.

app.get('/', (req, res) => {
	var cursor = db.collection('quotes').find()
})

O método find retorna um cursor (um objeto do Mongo) que provavelmente não faz sentido se você fizer console.log dele.

0_IQHvKZ7Bd5mIlxT0

A boa notícia é que esse objeto cursor contém todas as citações do nosso banco de dados. Ele também contém várias outras propriedades e métodos que nos permitem trabalhar com dados facilmente. Um desses métodos é o método toArray().

O método toArray recebe uma função de callback que nos permite fazer coisas com as citações que recuperamos do MongoLab. Vamos tentar fazer um console.log() para os resultados e ver o que obtemos!

db.collection('quotes').find().toArray(function(err, results) {
	console.log(results)  // enviar arquivo HTML preenchido com citações aqui
})
0_6McLqpFyG1xA5of1

Ótimo! Agora, você vê um array de citações (eu só tenho uma agora). Concluímos a primeira parte — obter dados do MongoLab. A próxima parte é gerar um HTML que contenha todas as nossas citações.

Não podemos servir nosso arquivo index.html e esperar que as citações apareçam magicamente porque não há como adicionar conteúdo dinâmico a um arquivo HTML. O que podemos fazer em vez disso é usar mecanismos de template para nos ajudar. Alguns mecanismos de template populares incluem Jade, Embedded JavaScript e Nunjucks.

Escrevi extensivamente sobre o como e o porquê dos mecanismos de template em uma artigo separado (em inglês). Você pode querer dar uma olhada se não tiver ideia do que são mecanismos de template. Eu pessoalmente uso (e recomendo) Nunjucks como meu mecanismo de template de escolha. Sinta-se à vontade para conferir o artigo para descobrir o porquê.

Para este tutorial, vamos usar Embedded JavaScript - ejs como nosso mecanismo de template porque é o mais fácil para começar. Você o achará familiar desde o início, pois já conhece HTML e JavaScript.

Podemos usar o EJS primeiro instalando-o e, em seguida, definindo o mecanismo de visualização no Express como ejs.

$ npm install ejs --save
app.set('view engine', 'ejs')

Depois que o mecanismo de visualização for definido, podemos começar a gerar o HTML com nossas citações. Esse processo também é chamado de renderização. Podemos usar o objeto render integrado ao objeto de resposta render para fazer isso. Ele tem a seguinte sintaxe:

res.render(view, locals)

O primeiro parâmetro, views, é o nome do arquivo que estamos renderizando. Esse arquivo deve ser colocado dentro de uma pasta views.

O segundo parâmetro, locals, é um objeto que passa dados para a visualização.

Vamos primeiro criar um arquivo index.ejs dentro da pasta views para que possamos começar a preencher os dados.

$ mkdir views$ touch views/index.ejs

Agora, coloque o seguinte código dentro de index.ejs.

<ul class="quotes">
	<% for(var i=0; i<quotes.length; i++) {%>
		<li class="quote">
      		<span><%= quotes[i].name %></span>
      		<span><%= quotes[i].quote %></span>
    	</li>
	<% } %>
</ul>

Viu o que eu quis dizer quando disse que você o acharia familiar? No EJS, você pode escrever JavaScript dentro de tags <% e %>. Você também pode gerar JavaScript como strings se usar as tags <%= e %>.

Aqui, você pode ver que estamos basicamente percorrendo o array quotes e criando strings com quotes[i].name e quotes[i].quote.

Mais uma coisa a fazer antes de prosseguirmos com o arquivo index.ejs. Lembre-se de copiar o elemento <form> do arquivo index.html para esse arquivo também. O arquivo index.ejs completo até agora deve ser:

<!DOCTYPE html>
<html lang="en">
	<head>
    	<meta charset="UTF-8">
        <title>MEU APP</title>
    </head>
    <body>
    	Que o Node e o Express estejam com você.
        <ul class="quotes">
        	<% for(var i=0; i<quotes.length; i++) {%>
            	<li class="quote">
                	<span><%= quotes[i].name %></span>
                    <span><%= quotes[i].quote %></span>
                </li>
            <% } %>
        </ul>
        <form action="/quotes" method="POST">
        	<input type="text" placeholder="nome" name="nome">
            <input type="text" placeholder="citação" name="citação">
            <button type="submit">Enviar</button>
        </form>
     </body>
</html>

Finalmente, temos que renderizar esse arquivo index.ejs ao lidar com a solicitação GET. Aqui, estamos definindo os resultados (um array) como o array quotes que usamos em index.ejs acima.

app.get('/', (req, res) => {
	db.collection('quotes').find().toArray((err, result) => {
    	if (err) return console.log(err)    // renderiza index.ejs
        res.render('index.ejs', {quotes: result})
    })
})

Agora, atualize seu navegador e você deverá ver as citações do Mestre Yoda.

0_Wy8S2Yag15rpIOlt

Ah, você pode ter apenas uma citação se seguiu o tutorial passo a passo até esse ponto. O motivo pelo qual tenho várias citações é porque adicionei mais silenciosamente enquanto trabalhava na aplicação.

Conclusão

Cobrimos muito terreno em apenas 3 mil palavras! Aqui estão alguns marcadores para resumir tudo. Você...

  • Criou um servidor Express
  • Aprendeu a executar operações CRIAR (CREATE) e LER (READ)
  • Aprendeu a salvar e ler no MongoDB
  • Aprendeu a usar um mecanismo de template como o Embedded JS.

Este artigo apareceu pela primeira vez no blog do autor (em inglês). Confira o blog se quiser ver mais artigos como este.