Você está na página 1de 59

Criando aplicaes web

com Node.js
Charles Viegas

charles.viegas@codate.com.br
@charlesviegas

Referncias
nodejs.org
http://expressjs.com/
https://github.com/expressjs/body-parser
https://github.com/expressjs/session
Livro: Node.js: aplicaes web real-time com Node.js
Caio Ribeiro
Casa do cdigo

Cdigo fonte da soluo


https://github.com/charlesviegas/minicurso-nodejs.git

INTRODUO AO NODE.JS

O que o Node.js?
Javascript no lado do servidor
Construdo sobre o engine V8 do Chrome
Executa por linha de comando
Projetado para alta concorrncia
Single thread
No bloqueante
Utiliza o framework CommonsJS

No bloqueia IO
Esperar pedidos de I/O degrada a performance.
O Node usa evento em JS para anexar retornos a chamadas
de IO.

Exemplo
BLOQUEANTE

NO BLOQUEANTE

...
String sql = "SELECT c FROM Contato";

var callback = function(err, rows) {


if(err) throw err;
console.log(rows);
});

Query q= em.createQuery(sql);

List result = query.getResultList();


...

con.query("SELECT * FROM Contato",


callback);

Event Loop
Ao invs de threads, o Node usa um loop de eventos,
aliviando o overhead da troca de contexto.

Instalao e Configurao
Acesse o site http://nodejs.org
Faa download do executvel e instale de forma padro
Verifique se a instalao funcionou corretamente executando
os comandos:
node version
npm --version

Prtica 1 - Ol Javaneiros
Abra o terminal e navegue para a pasta:
curso\pratica1

Execute o comando: node olajavaneiros.js


Observe a sada no prprio terminal

Execute o comando: node olajavaneiroshttp.js


Abra seu navegador e acesse a url impressa no terminal

NPM
Node Package Manager
Gerencia os mdulos do node, baixando da web os mdulos e suas
dependncias

Baseado em linha de comando


npm install nome_do_modulo --save
npm install g nome_do_modulo
npm remove nome_do_modulo
npm update nome_do_modulo
npm list

package.json
O Node utiliza o arquivo package.json para descrever os
metadados do projeto.
Nome, verso, dependncias

Deve estar presente na pasta raiz de cada projeto.

package.json
{

"name": nome_do_projeto",
"description": "Meu primeiro app em Node.js",
"author": Charles Viegas <charles@email.com>",
"version": "1.0.0",
"private": true,
"dependencies": {
"modulo-1": "1.0.0",
"modulo-2": "~1.0.0",
"modulo-3": ">=1.0.0"
},
"devDependencies": {
"modulo-4": "*"
}

Prtica 2 - Criando o package.json


Durante o curso iremos criar uma pequena aplicao para
controlar uma lista de presentes para casamento.
Crie a pasta raiz:
Nome: casalista

Crie dentro da pasta o arquivo:


Nome: package.json
Contedo: name, description, author, version e private

Execute dentro da pasta raiz o seguinte comando:


npm install

Prtica 2 - Criando o package.json


{

"name": casalista",
"description": App para lista de casamento em Node.js",
"author": Seu Nome <seuemail@email.com>",
"version": "1.0.0",
"private": true

Objetos globais
global: assim como nos browsers o Node tambm possui um
contexto de alto nvel.
process: contm os dados do processo de execuo.
console: usado para imprimir mensagens nas sadas de fluxo
padres.
Buffer: usado para manipular dados binrios.
require: usado para importao de mdulos

Objetos globais
__filename: o nome do arquivo que est sendo executado
__dirname: o nome do diretrio que reside o arquivo que est
sendo executado.
module: uma referncia para o mdulo corrente.

CommonJS
O Node utiliza nativamente o padro CommonJS para
organizao e carregamento dos mdulos.
modulo1.js
var m2 = require(./modulo2.js);
m2(Ola Javaneiros);

modulo2.js
module.exports = function(msg){
console.log(msg);
}

DOMINANDO EXPRESS

O que o Express?
Escrever cdigo usando a API HTTP do Node muito
trabalhoso.
O Express um mdulo para desenvolvimento de aplicaes
web de grande escala.

Caractersticas do Express
MVR (Model-View-Routes)
MVC (Model-View-Controller)
Roteamento de urls via callbacks
Middleware
Interface RESTFul
Suporte a File Uploads
Integrao com Template Engines

Mdulos do Express
A partir da verso 4, o Express passou a ser distribudo em vrios mdulos, sendo
eles:
express: Mdulo principal do express.
express-load: Carregamento dinmico de arquivos JS.
express-session: Controle de sesses do usurio.
method-override: Traduz mtodo POST para PUT e DELETE.
body-parser: Parser de campos do html para objeto JSON.
cookie-parser: Parser de cookie para objeto JSON.
ejs: Engine de template.

Prtica 3 - Instalando o express


Altere o seu package.json incluindo como dependncia as
ltimas verses dos mdulos:
express, express-load, express-session, method-override, bodyparser, cookie-parser e ejs

Dentro da pasta raiz execute o comando:


npm install

O npm vai criar a pasta node_modules e dentro delas todos


os seus mdulos

Prtica 4 Criando as pastas do


projeto
Copie para a pasta raiz do seu projeto a estrutura de pastas
e arquivos definida em curso\pratica4

Prtica 4 Criando as pastas do


projeto
controllers: vai conter os nossos controladores (MVC).
routes: vai conter os nossos roteadores.
public: vai conter os css e imagens.
views: vai conter as nossas views (MVC).
app.js: arquivo JS principal do nosso projeto.
Ateno: por questes de simplificao
no teremos o model (MVC) neste curso.

Iniciando um servidor Express


// Importa e instancia um servidor express
var express = require("express"),
app = express();
// Configuraes futuras
// Sobe o servidor HTTP na posta 3000
app.listen(3000, function () {
console.log(Servidor est no ar.");
});

Prtica 5 Iniciando um servidor


express
Conforme exemplo anterior altere o arquivo app.js
Execute o comando:
node app.js

Abra o navegador no endereo: http://localhost:3000


Voc deve receber a mensagem: Cannot GET /

Definindo views
...
// Configuraes futuras

// Define a pasta onde iro ficar as views


app.set("views", __dirname + "/views");
// Define o template engine usado nas views
app.set("view engine", "ejs");
...

Definindo contedo esttico


// Configuraes futuras

...
// Define a pasta public para contedo esttico
app.use(express.static(__dirname + "/public"));
...

Definindo as rota inicial


// Configuraes futuras

...
// Responde ao acessar o localhost:3000/
app.use("/", function(req, res){
res.send("Ola Javaneiros");
});
...

Prtica 6 Definindo views,


contedo esttico e rota inicial
Altere o arquivo app.js com os passos feitos nos ltimos trs
slides.
Reinicie o node visualizar as alteraes.

Para ver os resultados, abra seu navegador no endereo


http://localhost:3000/
Para testar o contedo esttico abra tambm o endereo
http://localhost:3000/app/css/style.css

Express-load
Utilizaremos o express-load que carrega modulos dentro da
instncia do express simplementes informando a pasta onde
estas scripts esto.
Portanto, ao invs de usar o require(nome_do_modulo), ns
utilizaremos o express-load para esta funo.

Express-load
// Importa o mdulo express-load
var express = require("express"),
load = require("express-load"),
app = express();
...
// Carrega todas as scripts da pasta controller e routes
load("controllers")
.then("routes")
.into(app);

Prtica 7 Express-load
Adicione o express-load conforme slides anteriores.
Reinicie o node visualizar as alteraes.

Criando Roteadores
comum que os roteamento no express fiquem separados em
mdulos externos para melhorar a legibilidade do cdigo.
Portanto iremos remover o cdigo abaixo da app.js:

app.use("/", function(req, res){


res.send("Ola Javaneiros");
});

Criando Roteadores
E criaremos um mdulo a parte s para roteamento.
module.exports = function (app) {
var home = app.controllers.home;
app.get("/", home.index);
app.post("/entrar", home.entrar);
};

Criando Controladores
Os controladores controlam a sequncia de execuo e a navegao entre
as pginas.
Tambm recomendvel a separao da sua lgica num mdulo separado.

module.exports = function (app) {


var HomeController = {
index: function (req, res) {
res.render("home");
},
entrar: function (req, res) {
}

};

};
return HomeController;

Prtica 8 Roteadores e
Controladores
Crie os roteadores e controladores conforme slides
anteriores.

Criando views com EJS


Para criao das Views utilizaremos o EJS.
O EJS permite imprimir o contedo de objetos JSON em
partes do html
Tambm permite a incluso de loops, estruturas condies e
includes

Criando views com EJS


Organizaremos nosso cdigo da seguinte forma:
header.ejs
footer.ejs
home.ejs

header.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Javaneiros - Lista de presentes de casamento</title>
<link rel="stylesheet" href="/bootstrap/css/bootstrap.css"/>
<link rel="stylesheet" href="/bootstrap/css/bootstrap-theme.css"/>
<link rel="stylesheet" href="/app/css/style.css" />
</head>
<body>

footer.ejs
<footer class="navbar navbar-default navbar-fixed-bottom">
<div class="container">
Javaneiros 2014
</div>
</footer>
<script src="/bootstrap/js/jquery.js"></script>
<script src="/bootstrap/js/bootstrap.js"></script>
</body>
</html>

home.ejs
<% include ./header %>
<div class="container">
<form action="/entrar" method="post" role="form" class="form-signin">
<h2>Lista de presentes</h2>
<input type="text" name="noivo" placeholder="Noivo" class="form-control"
required="required" autofocus="autofocus"/>
<input type="text" name="noiva" placeholder="Noiva" class="form-control"
required="required"/>
<button type="submit"
class="btn btn-lg btn-primary btn-block">Ver lista</button>
</form>
</div>
<% include ./footer %>

Prtica 9 Views
Crie as views header, footer e home conforme slides
anteriores.

Body-parser
O express utiliza o modulo body-parser para realizar a
converso dos dados submetidos por um formulrio html em
objeto JSON.

Body-parser
var express = require("express"),
bodyParser = require("body-parser"),
load = require("express-load"),
app = express();

// Inclui o parser para formato json


app.use(bodyParser.json());
// Inclui parser para urlencoded
app.use(bodyParser.urlencoded({extended: true}));
...

Express-session
Recurso que permite manter dados do usurio no servidor.
Para acessar o objeto a ser mantido na sesso basta
acessar req.session

Express-session
var express = require("express"),
bodyParser = require("body-parser"),
load = require("express-load"),
expressSession = require("express-session"),
app = express();

app.use(expressSession({
secret: "keyboard cat",
resave: false,
saveUninitialized: true
}));
...

Prtica 10 Body-parser e Session


Adicione o body-parser e o express-session conforme slides
anteriores.

Manipulando session
Agora iremos gravar na sesso do usurio os dados
submetidos pela tela de home.
Para isso, iremos alterar o controlador do home.

Manipulando Session
...
var HomeController = {
...
entrar: function (req, res) {
var lista = {
noivo : req.body.noivo,
noiva : req.body.noiva,
presentes : []
};
req.session.lista = lista;
res.redirect("/presentes");
}
};
...

Prtica 11 Manipulando session


Complete o cdigo do HomeController conforme slide
anterior.
Aps submeter o formulrio voc ver a seguinte mensagem:
Cannot GET /presentes

routers\presente.js
module.exports = function (app) {
var presentes = app.controllers.presentes;
app.get("/presentes", presentes.index);
app.get("/comprar/:id", presentes.comprar);
app.post("/presentes", presentes.incluir);
};

controllers\presente.js
module.exports = function (app) {
var PresentesController = {
index: function (req, res) {
res.render("presentes", {presentes: req.session.lista.presentes});
},
incluir: function (req, res) {
var lista = req.session.lista;
var presente = {
nome: req.body.nome,
valor: req.body.valor
};
lista.presentes.push(presente);
res.redirect("/presentes");
},
comprar: function (req, res) {
var id = req.params.id;
req.session.lista.presentes[id].comprado = true;
res.redirect("/presentes");
}
};
return PresentesController;
};

view\presentes.ejs
<% include ./header %>
<div class="container">
<div class="page-header">
<h1>Lista de presentes</h1>
</div>
<div class="row">
<! ****************** Formulrio -->
</div>
<div class="row">
<! ****************** Tabela -->
</div>
<div class="row">
<a href="/">Sair</a>
</div>
</div>
<% include ./footer %>

view\presentes.ejs - formulrio
<div class="col-xs-12">
<form action="/presentes" method="post" role="form">
<div class="row">
<div class="col-xs-4">
<input type="text" name=nome" placeholder="Presente"
class="form-control"/>
</div>
<div class="col-xs-4">
<input type="text" name=valor" placeholder="Valor"
class="form-control"/>
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-default">Incluir</button>
</div>
</div>
</form>
</div>

view\presentes.ejs - tabela
<div class="col-xs-12">
<table class="table table-bordered table-striped">
<thead><tr>
<th>Presente</th> <th>Valor</th><th>Ao</th>
</tr></thead>
<tbody>
<% presentes.forEach(function(presente, index) { %>
<tr>
<td><%- presente.nome %></td> <td><%- presente.valor %></td>
<td>
<% if (!presente.comprado) {%>
<a href="/comprar/<%- index %>">Comprar</a>
<%}%>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>

Prtica 12 Final
Crie o roteador, controlador e a view para a tela de presentes
conforme slides anteriores.