Criando um chat com Node.js e Socket.io

Node.js é uma tecnologia com menos de 10 anos, tendo sido lançada em 2009. No entanto, tem uns 5 anos que se tornou imensamente popular, desde que grandes nomes do mundo da tecnologia como Uber, Netflix e PayPal começaram a utilizá-la em produção.

Uma das principais características do Node.js, se não for sua principal, é o fato de trabalhar de maneira assíncrona, com requisições não bloqueantes e baseadas em eventos, o que o torna muito interessante para aplicações real-time. Aliado à isso temos e um ecossistema vibrante que cresce dia-a-dia com todo tipo de tecnologia auxiliar à plataforma, como o fantástico Socket.io.

Todo mundo que mexe com web já deve ter ouvido falar de websockets, Comet, etc. Esse tipo de tecnologia muito popularizado pelo Twitter nos idos de 2010-2012, promoveu uma revolução na forma de trabalhar comunicação cliente-servidor, cliente-cliente, real-time, etc. E Socket.io é justamente isso: uma tecnologia para comunicação real-time, bi-direcional, baseada em eventos.

Nesse post vamos explorar a criação de um aplicação de chat usando Node.js e Socket.io, visando dar uma introdução à tecnologia.

Veremos neste post:

  1. Introdução e Configuração
  2. Criando a aplicação web
  3. Programando o chat
  4. Indo além

Vamos lá!

#1 – Introdução e Configuração

Para este tutorial você precisa ter o Node.js instalado na sua máquina. Baixe e instale a versão mais recente para o seu sistema operacional. Usaremos sobre o Node.js o webframework Express (que eu já ensinei a usar antes), então abra o seu terminal de linha de comando e instale globalmente o módulo express-generator, que permite facilmente criar aplicações web com Express.

Muito provavelmente você terá de ter permissão de administrador para rodar o comando acima.

Agora, vamos criar um novo projeto Express usando o comando abaixo em que eu passo a view-engine (EJS, que usa HTML+JS), deixo o projeto preparado para o Git e passo o nome da pasta onde o projeto será armazenado.

Isso irá criar toda a estrutura mínima de pastas e arquivos para termos uma aplicação web funcionando com Express. Agora entre na pasta do projeto e rode um npm install para instalar as dependências:

Isso irá baixar todas as dependências necessárias para o básico funcionar. Mas ainda precisaremos de mais dependências!

Instale a dependência do módulo Socket.io usando o comando abaixo, que irá salvar esta dependência no seu arquivo package.json:

O Socket.io é dividido em duas partes: cliente em servidor. Essa dependência é a necessária para criar o servidor que rodará em nossa aplicação Node.js. Trabalharemos com o cliente mais tarde. Para deixar nosso servidor de chat já esperando conexões, abra o seu bin/www (que não possui extensão mas pode ser aberto por qualquer editor) e inclua o seguinte trecho de código que inicializa o servidor Socket.io e imprime uma mensagem no console toda vez que alguém “entra”no chat (que aqui basta acessar a página):

Esse código deve ficar depois do comando createServer.

Depois de instalar todas dependências e deixar pronto o rascunho do servidor de chat, apenas retorne à raiz do projeto e execute-o através do comando abaixo:

Se tudo deu certo, você deve abrir no seu navegador a URL localhost:3000 e ver a imagem abaixo:

Express funcionando
Express funcionando

Agora, para ver se o servidor Socket.io está funcionando realmente, vamos ter de implementar o lado do cliente.

#2 – Criando a aplicação web

Agora que temos todo nosso ambiente configurado, funcionando e sabemos o que vamos fazer, é hora de criar o front-end da nossa aplicação, que será bem “espartano”.

Na pasta views do seu projeto você encontrará arquivos .ejs que são as interfaces/layouts da sua aplicação web. Crie um novo arquivo chat.ejs (com qualquer editor de texto) e cole o seguinte conteúdo HTML dentro dele:

Para que essa view seja exibida no navegador, precisamos criar uma rota para ela. Fazer isso é bem fácil, entre na pasta routes e abra o arquivo index.js em seu editor de texto favorito. Dentro dele, adicione o seguinte bloco de código:

Isso quer dizer que, quando chegar uma requisição GET em /chat, renderizaremos a view chat.ejs. O resultado você confere abaixo, mandando rodar e acessando /chat no seu navegador:

Tela de Chat
Tela de Chat

A experiência do usuário com essa tela é bem simples: o usuário digita uma mensagem no campo e clica em Send para enviá-la. Obviamente nada disso funciona ainda.

O próximo passo é ajustar o lado do cliente para que ele se conecte em nosso servidor assim que entrar nessa tela. Para fazer isso, abra o nosso arquivo views/chat.ejs e inclua o seguinte trecho de código antes da tag </body>, lá pelo final do documento:

Esse código carrega a inicializa a biblioteca socket.io-client, que é um JS client-side que se conecta no server-side. Aqui eu não passei a URL do servidor para a função io(), sendo assim ele vai se conectar localhost mesmo.

Para ver se isto está funcionando, mande rodar novamente a sua aplicação e acesse a tela de chat, depois olhe no console. Acesse em várias abas diferentes e verá o comportamento abaixo no console:

Chat Server
Chat Server

Se quisermos saber também quando um usuário se desconectou do chat (ou seja, fechou a janela do navegador), podemos tratar isso com o evento disconnect. Lá em nosso bin/www, onde iniciamos o servidor de chat, altere o código para que seja impresso no console quando o usuário deixa a sala de chat:

Agora se iniciarmos novamente a aplicação e fizermos o mesmo procedimento de abrir e fechar abas, veremos um comportamento um pouco diferente:

Chat Server Funcionando
Chat Server Funcionando

E com isso agora temos tanto o client quanto o server da nossa aplicação de chat funcionando!

Curso Node.js e MongoDB
Curso Node.js e MongoDB

#3 – Programando o chat

A ideia principal por trás do Socket.io é que você pode enviar e receber quaisquer eventos que quiser, com os dados que quiser, usando objetos JSON ou binários mesmo.

Agora vamos programar o client-side da nossa aplicação para que quando o botão Send seja clicado, um evento ‘chat message’ seja disparado ao servidor com a mensagem escrita. Esse código deve ir no chat.ejs, no final do arquivo, substituindo o código anteriormente adicionado:

Agora temos de fazer com que nosso chat-server esteja preparado para lidar com esse evento. Sendo assim, abra o seu bin/www novamente e modifique o código do seu chat-server como abaixo:

Agora nosso chat-server já está recebendo mensagens. Se você executar a aplicação e escrever e enviar algumas mensagens, vai ver elas escritas no terminal do console.

Aqui a comunicação está sendo unidirecional: somente o server está recebendo as mensagens dos clientes. Nosso próximo passo é fazer com que as mensagens recebidas pelo server sejam propagadas para os clientes que estão na mesma sala de bate-papo. Para fazer isso, vamos mexer novamente no código do nosso chat-server em bin/www:

Para fazer a propagação da mensagem para todos os clientes, usamos o io.emit, passando o nome do evento que queremos propagar e os dados do evento, que aqui no caso é apenas a mensagem crua.

No entanto se você testar agora, verá que apesar do chat estar funcionando “por baixo dos panos”, não aparece nada na tela ainda. Isso porque ainda precisamos de uma última alteração no nosso front-end para tratar o recebimento deste evento e exibi-lo na tela do chat. Mude o bloco do client-side para o abaixo:

Agora sim, teste sua aplicação em mais de uma aba e verá que as mensagens enviadas por uma delas são repercutidas nas demais, como na imagem abaixo:

Chat Funcionando
Chat Funcionando

Legal não?!

#4 – Indo além

Esse tutorial termina aqui, mas existem diversas coisas que você pode estudar para aperfeiçoar esse chat. Dentre elas:

O Socket.io é bem extensível com seu modelo aberto de eventos e dados, logo, é muito simples customizá-lo para atender todo tipo de demandas, criando seus eventos personalizados.

Espero que tenham gostado!

Metade deste post é coberto pelos slides abaixo, de um workshop meu. O restante do workshop pode ser encontrado neste post de Android.

Fonte: este post foi claramente influenciado pela documentação oficial do Socket.io (em inglês).

Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu livro sobre programação web com Node.js!

Publicado por

Luiz Duarte

Pós-graduado em computação, professor, empreendedor, autor, Agile Coach e programador nas horas vagas.