Professional Documents
Culture Documents
A aplicao uma mini rede social voltil, oportunamente chamada de RAMBook, onde ser possvel criar
posts, coment-los e curti-los em tempo real, porm, cujos dados no sero persistidos em uma base de
dados ou sistema de arquivos.
Devido a essa caracterstica de no persistir os dados, qualquer usurio poder se conectar mini rede social
sem precisar se autenticar, e sempre que um novo usurio entrar, ser exibida a sua timeline vazia, um
campo de texto para criar novos posts e a lista de usurios conectados, como apresentado na Figura 1.
Twitter Bootstrap;
RequireJS;
MustacheJS;
jQuery;
Bower.
Socket.IO;
ExpressJS;
Nodemon.
Se voc ainda no tiver o NodeJS instalado em sua mquina, ou se possui uma verso muito antiga, acesse o
link de download do mesmo disponvel na seo Links e efetue o download para o seu sistema operacional,
realizando tambm a sua instalao.
Se for preciso, faa o mapeamento do diretrio bin nas variveis de ambiente do seu sistema operacional de
maneira a poder acessar os binrios node e npm de qualquer lugar.
Instalando as dependncias
Uma vez que o NodeJS estiver devidamente instalado e configurado, hora de instalar as dependncias do
projeto atravs do NPM, o Node Packaged Modules.
O NPM um repositrio de mdulos para NodeJS repleto de APIs que podem ser facilmente baixadas,
muito semelhante ao apt-get do Linux Debian, ou o Gem do Ruby.
Para nossa stack de backend vamos instalar o Socket.IO e o ExpressJS, e para as dependncias da camada de
front-end vamos utilizar o mdulo Bower, que funciona de uma maneira extremamente semelhante ao
prprio NPM. Porm o Bower gerencia APIs de JavaScript como jQuery e BackboneJS.
Existem outros mdulos muito bons para a criao de projetos web como o Grunt, Gulp e Yeoman, que
trabalham com geradores e utilizam o Bower e Grunt, colocando-os para trabalhar lado a lado de uma forma
mais automatizada.
Porm, para o nosso exemplo a HTML, CSS e cdigo JavaScript sero escritos do zero. Contudo, se voc
se sente confortvel em trabalhar com ferramentas automatizadas, fique vontade para utilizar o que
preferir.
Nota: Todos os links para download das ferramentas citadas encontram-se disponveis na seo Links.
Baixando as dependncias da camada server
Crie um diretrio chamado rambook e acesse-o para iniciar o download das dependncias.
Vamos comear pelas dependncias da camada server, utilizando o comando npm install conforme
mostrado na Listagem 1.
Listagem 1. Baixando as dependncias do backend.
npm install Socket.IO
npm install express
npm install nodemon -g
npm install bower -g
Note que para o download dos mdulos Nodemon e Bower utilizamos o parmetro -g, que responsvel por
efetuar o download dos mdulos e os instalar em um diretrio de mdulos globais, junto ao diretrio onde
voc instalou o NodeJS.
Ambos os mdulos possuem arquivos binrios, e podem ser executados como qualquer arquivo binrio do
seu sistema operacional.
Como j havia sido explicado anteriormente, o Bower funciona como um gerenciador de pacotes para APIs
JavaScript, muito semelhante ao NPM.
O Nodemon um watcher, que fica escutando quando qualquer arquivo dentro do diretrio for alterado,
e faz um refresh na aplicao NodeJS quando isso acontece. uma ferramenta que auxilia durante o
desenvolvimento da aplicao, porm no necessrio (nem recomendado) sua utilizao em ambiente de
produo.
H outras opes interessantes que podem ser usadas com o NPM, como preservar a referncia das
dependncias em um arquivo package.json com a opo --save, e assim poder distribuir a aplicao apenas
com os cdigos fonte em controladores de verso como o Github, sem precisar fazer upload das
dependncias. Assim, outros desenvolvedores que fizerem download da aplicao precisaro apenas digitar
o comando npm install e o NPM ir ler as dependncias do arquivo package.json.
Baixando as dependncias da camada client
Dentro do diretrio rambook, crie um diretrio chamado web e acesse esse diretrio, pois dentro dele que
iremos baixar as dependncias JavaScript/CSS, executando os comandos da Listagem 2.
Ainda no diretrio web, crie os diretrios scripts e styles, onde ficaro nossos arquivos CSS e JavaScript da
aplicao na stack de client.
Listagem 2. Baixando as dependncias da camada client.
bower install jquery
bower install bootstrap
bower install mustache
bower install requirejs
Aps o trmino dos downloads, voc pode notar um novo diretrio chamado bower_components que possui
uma estrutura de diretrio para cada API instalada pelo Bower.
Por default, o Bower busca as APIs no Github, mas voc pode especificar parmetros para acessar outras
fontes.
Alm disso, assim como o NPM, o Bower possui um parmetro --save que persiste a referncia das
dependncias em um arquivo bower.json.
Estrutura do projeto
At o momento temos uma estrutura de diretrios com todas as bibliotecas necessrias e prontas para
trabalhar, conforme exibido na Listagem 3.
Listagem 3. rvore de diretrios do projeto.
rambook
node_modules
express
Socket.IO
web
bower_components
scripts
styles
index.js, que servir como nosso main program e iniciar os servidores web e websocket;
server.js, responsvel por instanciar, configurar e exportar os servidores http e websocket;
userhandling.js, onde residir nossa regra de negcios para gerenciar as aes da mini rede social.
index.html, que ser a pgina da nossa aplicao. Este ser o nico HTML, pois faremos uma SPA,
Single Page Application;
styles/main.css, que conter o estilo de nossa aplicao
scripts/main.js, onde estar a configurao do RequireJS e servir como nosso main program;
scripts/client.js, onde estar nossa socket client que se comunicar com o servidor websocket;
scripts/view.js, responsvel por se comunicar com a client.js e fazer o link entre a websocket e os
eventos dos elementos HTML da pgina.
Ao trmino da criao dos arquivos da camada client e server, devemos ter uma estrutura como exibido na
Listagem 4.
Listagem 4. rvore de diretrios e arquivos do projeto.
rambook
index.js
node_modules
express
Socket.IO
package.json
server.js
userhandling.js
web
bower_components
bootstrap
jquery
mustache
requirejs
bower.json
index.html
scripts
client.js
main.js
view.js
styles
main.css
Note que foram omitidos arquivos das dependncias, como as do Socket.IO e ExpressJS.
Tambm foram omitidas as dependncias baixadas pelo Bower, pois como ele trabalha com os repositrios
das APIs do Github, muitos arquivos desnecessrios para o projeto esto armazenados.
Construindo a camada front-end da aplicao
Primeiro, vamos escrever o contedo de nosso HTML, que foi montado utilizando o Twitter Bootstrap.
Caso voc v digitar o contedo desse arquivo, sugiro que utilize algum template, como os exemplos
fornecidos pelo site do Bootstrap, ou utilize uma ferramenta de automatizao como o Yeoman, ou ainda,
5
utilize uma IDE que facilite a digitao de cdigo com macros e auto-complete text como o Sublime Text,
por exemplo.
Entendendo a estrutura do HTML
Se voc j estiver familiarizado com o Bootstrap, no encontrar problemas para entender o cdigo.
Contudo, para facilitar a compreenso de todos, segue uma explicao de como o cdigo HTML est
organizado:
No topo do cdigo, temos o tradicional cabealho, onde esto sendo importados os estilos CSS e o
tema do Bootstrap, o ttulo da pgina e demais tags como a <meta>;
A tag <nav> que marca o header da aplicao, onde reside o nome da aplicao e o formulrio de
login;
A lista de usurios conectados a mini rede social apresentada na tag <ul>;
Uma tela de boas vindas, solicitando ao usurio para que faa o login e possa ento acessar o
sistema;
Um <div> oculto com o campo de texto para criar posts e a timeline do usurio;
Tags <script> com o atributo type configurado para text/template, onde esto os templates a serem
utilizados pelo Mustache na hora de renderizar os fragmentos da aplicao;
E, finalmente, o include do RequireJS e seu arquivo principal.
type="text/css"
type="text/css"
<ul class="online-users"></ul>
</div>
<div class="col-md-9">
<div id="not-logged">
<h2>Voc precisa se conectar</h2>
<h3>Digite seu nome e clique em "Entrar"</h3>
</div>
<div id="logged" class="hidden">
<div class="post-form">
<div class="action">O que voc tem em mente?</div>
<textarea class="txt" id="post-content"></textarea>
<div class="pull-right">
<button class="btn btn-info glyphicon glyphicon-ok"
id="btn-postar"> Enviar</button>
</div>
</div>
<div class="posts"></div>
</div>
</div>
</div>
</div>
<script type="text/template" id="userlist-template">
{{#users}}
<li data-user-id="{{id}}"><span class="glyphicon glyphicon-user"></span>
{{username}}</li>
{{/users}}
</script>
<script type="text/template" id="post-template">
{{#post}}
<div class="post" data-post-id="{{id}}">
<div class="poster-info">
<span class="poster">{{author}}</span>
<span class="action">escreveu, as </span>
<span class="time">{{hora}} hs</span>
</div>
<div class="post-body">{{text}}</div>
<div class="post-actions">
<a class="glyphicon glyphicon-thumbs-up lnk-like-post" data-postid="{{id}}" data-like="true">(0)</a>
<a class="glyphicon glyphicon-comment lnk-comment" data-postid="{{id}}"></a>
</div>
<div data-post-to-comment-id="{{id}}" class="comment-form hidden">
<div class="action">Deixe seu comentrio</div>
<textarea class="txt"></textarea>
<div class="pull-right">
<button class="btn btn-info btn-sm glyphicon glyphicon-ok
btn-commentar"> Enviar</button>
<button class="btn btn-info btn-sm glyphicon glyphicon-remove
lnk-cancel-comment" data-post-id="{{id}}"> Cancelar</button>
</div>
</div>
<div class="post-comments"></div>
</div>
{{/post}}
</script>
<script type="text/template" id="comment-template">
{{#comment}}
data-
Note na listagem que ambos os includes de CSS e do RequireJS esto apontando para o diretrio
bower_components, e em seguida, para os respectivos diretrios de cada biblioteca, com exceo de nosso
prprio CSS, que est sendo direcionado para styles/main.css. O contedo do arquivo main.css pode ser
visto na Listagem 6.
Vale destacar que, caso voc decida fazer o deploy de sua aplicao com as APIs contidas no diretrio
bower_components, voc deve excluir os arquivos desnecessrios, ou copiar as APIs para outro diretrio, ou
ainda, preferivelmente, utilize uma ferramenta de automatizao como as tasks do Grunt para realizar essa
tarefa para voc.
Listagem 6. Contedo do arquivo de estilos styles/main.css.
body {
background-color: rgb(245, 245, 245);
overflow-y: scroll;
}
#frm-join {
color: #fff;
}
#log {
font-size: 25px;
text-align: center;
color: red;
}
.post {
border-bottom: 1px solid #aaa;
margin-top: 25px;
}
.poster-info {
font-size: 120%;
margin-bottom: 5px;
padding: 5px;
}
.poster {
color: #2aabd2;
font-weight: bold;
}
.post-body {
min-height: 30px;
color: #555;
padding: 5px;
}
.post-actions {
text-align: left;
padding: 10px;
}
.post-comments {
border-top: 1px dotted #bbb;
}
.comment {
font-size: 90%;
padding-left: 20px;
}
.post-form, .comment-form {
overflow: auto;
padding: 10px;
background-color: rgb(235, 235, 235);
border-radius: 5px;
}
.post-form {
font-size: 150%;
background-color: rgb(220, 220, 220);
}
.txt {
width: 100%;
height: 75px;
border: none;
border-radius: 5px;
margin-bottom: 10px;
}
.online-users {
list-style-type: none;
font-size: 130%;
color: #555;
}
a {
text-decoration: none !important;
cursor: pointer;
}
O cdigo autoexplicativo: trata-se basicamente de um objeto literal com as configuraes do caminho base
dos mdulos, os caminhos para os mdulos jQuery, Mustache e nossa websocket client, gentilmente
fornecida pelo prprio Socket.IO server, como veremos mais frente.
Ao final do cdigo, importado o mdulo view, referente ao arquivo view.js, que pode ser analisado na
Listagem 8 e ento este executado.
Listagem 8. Arquivo view.js.
require(['jquery', 'client', 'mustache'], function($, client, Mustache) {
var username = $('#username'),
onlineUsers = $('.online-users'),
postContent = $('#post-content'),
frmJoin = $('#frm-join'),
posts = $('.posts'),
notLogged = $('#not-logged'),
logged = $('#logged'),
userlistTpl = $('#userlist-template').html(),
postTpl = $('#post-template').html(),
commentTpl = $('#comment-template').html(),
lnkComment = $('.lnk-comment');
//Formatador da hora para o mustache
function formatHour() {
var today = new Date(this.timestamp);
return today.getHours() + ':' + today.getMinutes();
}
/*********DECLARAO DE EVENTOS**********/
$('.container')
.on('click', '#btn-entrar', function(ev) {
var name = username.val();
if(name) {
client.userLogin(name);
}
})
.on('click', '.lnk-comment', function(ev) {
var postId = $(this).data('post-id');
10
11
client.events.userlist = function(data) {
var html = Mustache.render(userlistTpl, {users: data});
onlineUsers.html(html);
};
client.events.makepost = function(data) {
var html = Mustache.render(postTpl, {post: data, hora: formatHour});
posts.prepend(html);
};
client.events.makecomment = function(data) {
var html = Mustache.render(commentTpl, {comment: data, hora: formatHour}),
postComments = $('.post[data-post-id="' + data.postId + '"] .post-comments');
postComments.prepend(html);
};
client.events.likepost = function(data) {
var lnkLikePost = $('.post[data-post-id="' + data.postId + '"] .lnk-like-post');
lnkLikePost.html('(' + data.numLikes + ')');
};
client.events.likecomment = function(data) {
var lnkLikeComment = $('.comment[data-comment-id="' + data.commentId + '"] .lnklike-comment');
lnkLikeComment.html('(' + data.numLikes + ')');
};
});
Apesar de ser um pouco longo, o arquivo view.js muito simples de ser entendido, pois ele a ligao entre
a interao do usurio e a comunicao com a websocket client, que por sua vez se comunica diretamente
com o nosso servidor websocket.
No topo do arquivo, pode-se notar a importao das dependncias do jQuery, usado para ler elementos
DOM do nosso index.html e realizar binds das aes do usurio, o MustacheJS usado para fazer a cola dos
dados recebidos do servidor e os templates que vimos nas tags <script> na HTML, e, finalmente, a
importao da nossa camada de negcios, client.js, que pode ser vista na Listagem 9.
Listagem 9. Regras de negcio da camada client client.js.
define(['socketio'], function(io) {
var socket = io.connect('/'),
events = {};
socket.emit('likecomment', {});
socket.emit('unlikecomment', {});
//listeners
socket.on('connect', function(data) {
events.connect(data);
});
socket.on('msg', function(data) {
console.log(data);
});
socket.on('userlogin', function(data) {
events.userlogin(data);
});
socket.on('userlist', function(data) {
12
events.userlist(data);
});
socket.on('makepost', function(data) {
events.makepost(data);
});
socket.on('makecomment', function(data) {
events.makecomment(data);
});
socket.on('likepost', function(data) {
events.likepost(data);
});
socket.on('likecomment', function(data) {
events.likecomment(data);
});
//emits
function userLogin(username) {
socket.emit('userlogin', {username: username});
}
function makePost(post) {
socket.emit('makepost', post);
}
function makeComment(comment) {
socket.emit('makecomment', comment);
}
function likePost(likeData) {
socket.emit('likepost', likeData);
}
function likeComment(likeData) {
socket.emit('likecomment', likeData);
}
return {
socket: socket,
userLogin: userLogin,
makePost: makePost,
makeComment: makeComment,
events: events,
likePost: likePost,
likeComment: likeComment
};
});
Muito semelhante ao view.js, o arquivo client.js est dividido em listeners e eventos, chamados de emits
pelo Socket.IO, o qual entraremos em mais detalhes a seguir.
Note que a nica dependncia do client.js a API do Socket.IO, um framework responsvel por se
comunicar com o servidor de websocket.
Entendendo o Socket.IO no lado do client
Fazendo uso da programao orientada a eventos do NodeJS, a proposta do Socket.IO oferecer de forma
transparente ao programador as diversas maneiras de se trabalhar com conexes persistentes entre o browser
e o servidor.
13
A maneira mais coerente de fazer isso atravs da API de Websocket, apresentada na especificao da
HTML5.
A maioria dos browsers hoje em dia j possuem a implementao dessa especificao, porm, alguns
browsers mais antigos no contam com a API da Websocket.
Nesses casos h diversas solues como o polling, long polling, Flash Websocket e outros mais que tem a
caracterstica de simular de forma paliativa o comportamento de uma websocket.
Quando o programador precisa se preocupar com os vrios browsers e verses, uma poro de validaes
precisam ser feitas para identificar qual a soluo mais adequada para lidar com conexes persistentes. E o
pior, ter que implementar todas elas de forma a atender todos os pblicos.
Com o advento do combo NodeJS + Socket.IO essa dor de cabea terminou, e o programador pde se
concentrar nas regras de negcio da aplicao.
Quando o browser se conecta atravs da API do Socket.IO.js, este se encarrega de fazer as devidas
validaes, preparar o contorno mais coerente, se necessrio, e se comunicar com o servidor passando todas
essas informaes.
Alm do mais, caso o browser do usurio possua suporte a Websockets, uma srie de passos precisam ser
seguidos para conectar o usurio ao servidor, como o handshake, que uma comunicao HTTP inicial
responsvel por validar e autenticar o usurio no servidor, at a conexo com o servidor da Websocket de
fato.
Aprendendo a lidar com a API do Socket.IO
Diferentemente do protocolo HTTP tradicional, quando emitimos um evento ao servidor da Websocket, no
ficamos pendurados ao servidor at que este retorne uma resposta de contedo ou uma mensagem de erro.
Ao invs disso, e devido ao seu comportamento orientado a eventos assncronos e no bloqueantes,
acabamos criando nosso prprio mini protocolo de comunicao. Ou seja, por um lado, emitimos uma
mensagem ao servidor, e precisamos declarar uma escuta para ouvir a resposta do mesmo, que pode
acontecer a qualquer momento, e no imediatamente aps receber nossa mensagem.
Por isso, basicamente o Socket.IO trabalha com duas funes emit e on, como pde ser visto no client.js. Ou
seja, quando queremos emitir uma mensagem ao servidor, usamos a funo emit, seguida de um nome de
evento definido pelo programador e os dados a serem recebidos pelo servidor.
Quando queremos escutar um evento recebido do servidor, precisamos implementar a funo on, cujos
parmetros so uma string com o nome do evento, e uma funo de callback cujo parmetro a informao
enviada pelo servidor.
Por exemplo, quando queremos saber se um usurio est logado, utilizamos o evento userlogin, como no
exemplo abaixo:
socket.on('userlogin', function(data) {
events.userlogin(data);
});
Note que estamos escutando o evento userlogin, e os dados recebidos pelo parmetro data so enviados para
o objeto events, que ser posteriormente lido pelo view.js.
14
Por outro lado, quando queremos notificar o servidor de que um novo usurio quer se conectar, emitimos o
evento com o nome userlogin. Utilizamos o mesmo nome para eventos que representam a mesma ao para
facilitar o entendimento:
function userLogin(username) {
socket.emit('userlogin', {username: username});
}
A maneira como a comunicao orientada a eventos funciona ficar mais clara quando virmos o cdigo do
servidor.
Construindo a camada backend da aplicao
Recapitulando a estrutura de arquivos da nossa camada do servidor, possumos trs arquivos: index.js,
server.js e userhandling.js.
O contedo do index.js, exibido na Listagem 10, bastante intuitivo.
Listagem 10. Contedo do index.js.
//Carrega o mdulo server.js
var Server = require('./server'),
//Carrega o objeto io
socketServer = Server.socketServer,
//Carrega o objeto httpServer
webServer = Server.webServer,
UserHandling = require('./userhandling'),
userHandling = new UserHandling(socketServer);
//Inicia o web server na porta 9000
webServer.listen(9000);
O arquivo index.js muito simples, pois apenas instancia os mdulos de nossa aplicao e faz a unio
destes, iniciando finalmente o servidor.
Primeiro, so importados os mdulos em variveis, como socketServer que retm a referncia ao Socket.IO,
webServer com a referncia ao servidor Web e o objeto userHandling, que possui toda a regra de negcio da
nossa mini rede social voltil.
Ento, o servidor web iniciado na porta 9000 e o objeto userHandling linkado ao servidor da Websocket.
O arquivo server.js, que pode ser analisado na Listagem 11, bem como o index.js, faz referncia aos
mdulos do ExpressJS e Socket.IO. Ento finalmente os instancia e os prepara para serem utilizados pelo
index.js.
Listagem 11. Contedo do arquivo server.js.
process.title = 'TTT Server';
//Importando ExpressJS
var express = require('express'),
//Importando Socket.IO
socketio = require('Socket.IO'),
15
16
socket.on('userlogin', function(data) {
that.onUserLogin(socket, data);
});
socket.on('userlist', function(data) {
that.onUserList(socket, data);
});
socket.on('makepost', function(data) {
that.onMakePost(socket, data);
});
socket.on('makecomment', function(data) {
that.onMakeComment(socket, data);
});
socket.on('likepost', function(data) {
that.onLikePost(socket, data);
});
socket.on('likecomment', function(data) {
that.onLikeComment(socket, data);
});
},
onDisconnect: function(socket) {
delete this.loggedUsers[socket.id];
this.onUserList(socket);
},
sendMessage: function(socket, msg) {
socket.emit('msg', {text: msg, type: 'info'});
},
onUserLogin: function(socket, data) {
var that = this;
if(data.username) {
socket.handshake.username = data.username;
that.loggedUsers[socket.id] = socket;
socket.emit('userlogin');
that.onUserList(socket);
} else {
this.sendMessage(socket, 'vc precisa escolher um nome');
}
},
onUserList: function(socket, data) {
var that = this,
keys = Object.keys(this.loggedUsers),
userList = new Array(keys.length),
i = 0;
keys.forEach(function(k) {
userList[i++] = {
id: k,
username: that.loggedUsers[k].handshake.username
};
});
socket.emit('userlist', userList);
socket.broadcast.emit('userlist', userList);
},
17
18
}
};
Embora um pouco mais comprido do que os outros arquivos da camada de backend, o arquivo
userhandling.js se assemelha muito sua verso da camada client.
Alm dos eventos tradicionais referentes rede social, como logar usurio, fazer post, comentrios e likes, o
userhandling possui dois eventos especiais: connection e disconnect.
O evento connection disparado logo aps o handshake, ou seja, logo aps o client se comunicar com o
servidor atravs de uma comunicao utilizando o protocolo HTTP.
Uma vez que ambos client e server apertam as mos uns dos outros, o servidor permite ao client o acesso
a websocket.
Ao mesmo passo em que, quando um usurio se desconecta do servidor, seja por ter fechado o browser ou
ter disparado uma ao de desconexo, o evento disconnect acionado e uma srie de aes realizada.
No nosso caso, quando o evento connection disparado, fazemos o bind de todos os eventos que o server ir
escutar do client e vice-versa, e tambm emitimos um evento userlist dizendo a todos os usurios conectados
que um novo usurio entrou na rede social.
Da mesma maneira, o evento disconnect remove o usurio da lista de usurios online e avisa a todos os
outros usurios, atravs do objeto socket.broadcast.emit com a nova lista de usurios online.
Outro ponto interessante a maneira como estamos lidando com as curtidas de posts e comentrios. Como
no temos uma maneira de persistir os dados em disco, foi criado o objeto this.posts, como pode ser visto no
comeo do arquivo userhandling.js. Este objeto mantm um histrico do id dos posts e quantas curtidas eles
receberam. Para se ter uma noo de como este controle funciona, d uma olhada nas funes
onLikeComment e onLikePost. Os ids dos posts foram feitos com o timestamp da hora do post.
Como havamos comentado anteriormente, foram usados os mesmos nomes de eventos em ambos os lados
do client e servidor, para garantir uma melhor legibilidade do cdigo. Ou seja, se o server recebe um evento
makepost, ao concluir a incluso do post na timeline, ele informa o prprio usurio e os demais usurios
com um evento de mesmo nome.
Juntando as peas
Agora que escrevemos ambas aplicaes no lado cliente e servidor, hora de execut-la!
V para o diretrio raiz rambook e execute o comando nodemon index.js.
Como mencionamos anteriormente, o Nodemon uma ferramenta que executa um programa NodeJS, no
nosso caso, index.js, e fica escutando por alteraes no cdigo. Toda vez que uma alterao feita em um
dos cdigos contidos no diretrio onde o Nodemon foi executado, ele recarrega toda a aplicao. Isso evita
com que voc tenha que parar o servidor e inici-lo novamente para cada alterao que fizer.
Aps executar o Nodemon, voc dever ver uma tela semelhante apresentada na Listagem 13.
Listagem 13. Servidor de websocket em ao.
chamb@selmy:~/Dropbox/projetos/tttserver$ nodemon index.js
20 Jan 21:14:06 - [nodemon] v0.7.10
20 Jan 21:14:06 - [nodemon] to restart at any time, enter `rs`
19
Agora podemos finalmente testar a aplicao, abrindo o browser e acessando a URL http://localhost:9000/.
Voc dever ver uma tela conforme exibido na Figura 2.
20
E, embora o NodeJS seja uma tecnologia muito empolgante, lembre-se de que ele no uma bala de prata, e
ainda que possa ser usado para desenvolver praticamente qualquer tipo de aplicao, cada tecnologia tem
seu paradigma e especialidade, que, no caso do NodeJS trabalhar com a programao orientada a eventos e
concorrncia.
Links
Download
http://nodejs.org/download/
do
Exemplos
de
uso
http://getbootstrap.com/getting-started/#examples
Site
http://www.sublimetext.com/
NodeJS
do
do
Sublime
Bootstrap
Text
Site
http://Socket.IO/
do
Socket.IO
Site
http://requirejs.org/
do
RequireJS
Site
https://npmjs.org/
do
22
NPM