Como Criar um Servidor em Node.js

O desafio neste post é criar um servidor em Node.js, organizando os arquivos de maneira que facilite a manutenção do projeto à medida que ele cresce.

Me acompanhe que eu vou desde o básico, evoluindo gradativamente até chegarmos no objetivo.

Primeiro vamos criar o servidor em um arquivo único. Obviamente, antes de iniciar, você precisa ter o Node instalado em sua máquina.

O Node é uma engine que permite a execução de código JavaScript fora do navegador. Isso deu a possibilidade de passarmos a utilizar JavaScript, que já dominava o client-side, também no server-side.

A fim de testar se o Node está ou foi devidamente instalado em sua máquina, abra uma janela do terminal e digite node -v. Isso deve retornar a versão do node, indicando que ele está acessível e pronto para ser utilizado.

Checar a versão do node.

Crie uma pasta no local que você preferir, onde será configurado o servidor. A minha vai se chamar servidor-node.

Navegue para dentro da pasta. Se você tiver dúvidas a respeito de como trabalhar com o terminal, os dois artigos a seguir podem te ajudar, tanto no caso do Linux/Mac quanto do Windows.

Navegar para dentro da pasta onde será criado o servidor.

O Node também possui o npm (Node Package Manager) um gerenciador de pacotes. Ele geralmente é instalado juntamente com o Node, mas para desencargo, você também pode executar um npm -v no terminal.

Agora então vamos, de fato, iniciar o projeto. O comando para isso é o npm init.

Este utilitário irá me guiar pelos primeiros passos, permitindo informar coisas como o nome do projeto, versão, descrição, etc.

Alguns campos já vêm com uma sugestão, como é o caso do nome e da versão. Caso você não queira o valor que já veio preenchido, basta informar o novo valor, da forma como fizemos para o campo versão, ilustrado na imagem abaixo.

Iniciar um projeto node.

Um campo que merece nossa atenção neste ponto é o entry point, pois é o arquivo informado nele que será executado para iniciar nossa aplicação.

Geralmente esse arquivo é chamado de index.js, motivo que justifica a sugestão para o campo.

Quando você termina de preencher os campos e pressiona Enter, é gerado dentro da pasta do seu projeto um arquivo de extensão json com os dados informados.

Arquivo de descrição do projeto node criado.

Como o entry point será o index.js, precisamos criar este arquivo em nosso projeto. Utilize a IDE que você preferir, eu vou de Sublime Text.

Criando entry point em um projeto node.

Quando desenvolvemos uma aplicação, frequentemente utilizarmos bibliotecas externas. Aqui no Node, elas são chamadas de libs.

Vamos utilizar uma lib aqui chamada Express, que implementa toda a parte das requisições e respostas com o protocolo http para que o cliente, geralmente um navegador, possa trocar informações com o servidor.

Instalaremos a lib do Express com o gerenciador de pacotes npm, começando com o comando npm install. Também vamos pedir para que essa informação seja salva acrescentando o parâmetro --save e, em seguida, o nome da lib: express. O comando completo encontra-se abaixo:

npm install --save express

Aí você pode estar se perguntando: mas onde isso é salvo? Bom, o package.json descreve o projeto. Se você der uma olhada novamente no arquivo, vai perceber que foi adicionado a ele uma nova chave, a chave das dependências, ou seja, de que este projeto depende para funcionar.

Você também deve ter reparado no surgimento de uma nova pasta no projeto, chamada node_modules. É alí que ficam os arquivos das dependências listadas no package.json.

Chave das dependências de um projeto node.

Antes de você compartilhar o projeto com outra pessoa ou executá-lo em outra máquina, é uma boa prática remover a pasta node_modules. Dessa forma, quando a outra pessoa receber o projeto, ela deve executar o comando npm install que irá ler o arquivo package.json e baixar novamente as dependências de acordo com a arquitetura de sua máquina e sistema operacional.

O próximo passo é importar esse módulo que acabamos de baixar, para dentro do nosso arquivo index.js.

Em Node, quando queremos importar um módulo, utilizamos a expressão require.

O que vamos fazer neste ponto, é criar uma constante chamada express que irá receber a importação do módulo express.

const express = require('express');
Importando um módulo num projeto node.

Com a linha de código acima, apenas carregamos o módulo Express na constante. Precisamos ainda criar uma instância desse objeto e guardá-la em uma nova constante, que denominaremos de app.

const app = express();
Chamando uma função em JavaScript.

Ok, agora toda vez que nos referirmos à app, estaremos falando do Express.

Para colocar um servidor de pé, a primeira coisa que devemos fazer é dizer que ele estará pronto para ouvir requisições em uma determinada porta. Então vamos pegar a app, executar o método listen informando a porta. Por convenção, os Servidores Node escutam na porta 3000, mas nada impede de você escolher qualquer outra.

app.listen(3000);

Só isso já é suficiente para que tenhamos uma thread rodando. Mas do jeito que está, não terá como ver se está ou não funcionando. Para que tenhamos algum feedback, vamos passar como segundo parâmetro do método listen, uma função callback que vai me mostrar um log com a seguinte mensagem: "Servidor ouvindo na porta 3000".

Colocando um Servidor Node de pé com o método listen do Express.

E por fim, estando com o terminal dentro da pasta onde encontra-se nosso arquivo index.js, podemos executá-lo utilizando o Node. Isso é feito escrevendo-se node, espaço, nome do arquivo.

node index.js
Executando um script com node pelo terminal.

O log comprova que o servidor está rodando. Mas se abrirmos o navegador e fizermos uma requisição para o endereço localhost na porta 3000, ainda não veremos nada porque o navegador tentará fazer uma requisição http do tipo get para a rota barra /, e ainda não definimos o que o servidor deve fazer ao receber um get para essa rota.

Acessando localhost na porta 3000.

Criaremos esta rota utilizando o método get do Express. O método receberá como primeiro parâmetro, uma string determinando a rota e, como segundo parâmetro, uma função callback onde será declarado o que faremos quando essa rota for acessada.

Nessa função callback, nós vamos receber como parâmetro dois objetos: um referente ao request, que eu vou abreviar para req e outro referente ao response, que vou chamar de res.

No corpo da função, vou pegar o objeto res e chamar o método send, para enviar uma resposta ao navegador dizendo que a rota barra foi acessada.

Criando rota barra.

Executando novamente o servidor e acessando o endereço localhost:3000 no navegador, obtemos a resposta programada.

Rota barra atendida.

Arquiteturando melhor o projeto

Em um projeto grande, provavelmente o Express vai receber várias customizações e muitas rotas serão criadas.

Além do mais, o arquivo index.js está com muitas responsabilidades. Ele importa o Express, cria uma instância do mesmo, inicia o servidor e atende requisições. Quando deveria somente ser responsável por iniciar o servidor.

A primeira coisa que vamos fazer então, é remover as configurações do Express para um arquivo à parte, que iremos chamar de custom-express. Este arquivo estará dentro de uma pasta denominada config, afinal, são configurações.

Pasta config contento o arquivo custom-express.

O arquivo foi chamado de custom-express porque ali irão se concentrar todas as customizações referentes ao Express, que provavelmente serão necessárias à medida que o projeto for crescendo.

E agora, no arquivos index.js, em vez de importar o Express padrão através do require, importaremos o Express customizado.

Importando Express customizado no arquivo index.js.

Referente à string de importação do nódulo na imagem acima, o que eu fiz foi partir da pasta atual ., entrar na pasta config /config e acessar o módulo criado por nós, /custom-express.

Se o require importa, a sintaxe que exporta um módulo é a module.exports. Portanto, para que nosso servidor continue funcionando, precisamos fazer essa declaração lá no módulo do Express customizado.

Exportar um módulo em Node.

Agora é hora de colocar as nossas rotas também em um arquivo separado. Vou criar a pasta rotas no projeto e, dentro dela, o arquivo raiz.js que vai conter a única rota que temos até o momento.

Colocando as rotas de um projeto Node em um arquivo separado.

Farei a importação das rotas lá no Express, que é justamente o cara responsável por cuidar delas.

O meu módulo rotas vai estar configurado para que, ao ser chamado, retorne uma função com as rotas. Por isso, logo após a importação, irei chamar essa função, justamente para obter as rotas. É como se eu encaixasse todas as rotas justamente naquele ponto onde a função foi chamada.

Importando as rotas para dentro do Express.

Na string de importação do módulo rotas, o meu ponto inicial é o arquivo custom-express.js e o objetivo é acessar o arquivo rotas.js. Para isso, primeiramente naveguei para fora da pasta atual .., depois, entrei na pasta rotas /rotas e acessei o arquivo raiz.js /raiz.

E por último, para que tudo continue funcionando, vamos então exportar a tal função com as rotas.

Exportando função de um módulo node.

Abstraindo um pouco os caminhos de pasta

Organizado do jeito que está, já é melhor do que em um arquivo só. Porém, todo novo conjunto de rotas que formos criando, teremos que importar manualmente no Express. Essa solução é um pouco engessada, ou como o pessoal gosta de falar para ficar mais chique: hard-coded, ou seja, se mudarmos a estrutura de pastas do projeto, ele quebra.

Isso é ruim porque a mudança, inevitavelmente, vai ocorrer. Essa é a única certeza que temos.

Nesse sentido, iremos lançar mão de um módulo chamado consign que irá nos auxiliar na organização das pasta do projeto.

Faremos a instalação dessa lib, com o já conhecido gerenciador de pacotes do node, o npm.

npm install --save consign

Depois de instalado, importamos o Consign no arquivo onde estamos customizando o Express, invocamos o mesmo através da sintaxe consign(), e aí, basta mandar incluir a pasta rotas .include('rotas') dentro da app, .into(app);.

consign().include('rotas').into(app);
Importar rotas através do Consign em um projeto Node.

Com isso, toda nova rota já será importada automaticamente. Tanto isso é verdade que, se rodarmos novamente nosso servidor, já veremos logs do Consign com os arquivos detectados dentro da pasta rotas.

Consign detectando rotas automaticamente.
Ir para o topo