ExpressJSEsse post é uma continuação da série de posts sobre NodeJS. Se você ainda não sabe o que ele é, como instalar, veja a tag NodeJS aqui no blog para se inteirar.

Já está na hora de fazer uma aplicação web de verdade com o Node, e nesse post eu vou te mostrar como isso é absurdamente simples. Vou usar um framework web que ficou muito popular no Node chamado ExpressJS, que é muito parecido com os conhecidos Rails, ASP.NET MVC, Play, etc, com a diferença de que ele não é um MVC, é um MVR (Model View Router), se bem que ele não tem opinião alguma sobre o Model, então ele está mais para VR do que pra MVR.

Assumindo que você já tem o node instalado, utilizar o Express é bem fácil. A maneira mais simples é instalar o npm dele globalmente, o que vai expor o comando “express”, que permite iniciar um projeto de forma fácil. Pra instalar (o $ significa a linha de comando onde estou):

$ npm install -g express

A versão atual é a 3.4.0. Você verá alguma coisa assim após a instalação:

[email protected] /home/giovanni/.nvm/v0.10.10/lib/node_modules/express
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] ([email protected])
├── [email protected] ([email protected])
└── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected])

Com isso, se você rodar:

$ express web

Ele vai inicializar o diretório “web” com os arquivos de base do Express. Se quiser instalar no diretório em que você está, faça:

$ express .

Se o diretório tiver algum arquivo ele vai perguntar se você quer mesmo instalar, porque ele pode sobrescrever algum arquivo. Usar o comando “express” não é obrigatório, você poderia montar a estrutura toda manualmente, mas daria mais trabalho. Após inicializar você verá isso:

$ express web

   create : web
   create : web/package.json
   create : web/app.js
   create : web/public
   create : web/public/javascripts
   create : web/routes
   create : web/routes/index.js
   create : web/routes/user.js
   create : web/public/images
   create : web/views
   create : web/views/layout.jade
   create : web/views/index.jade
   create : web/public/stylesheets
   create : web/public/stylesheets/style.css

   install dependencies:
     $ cd web && npm install

   run the app:
     $ node app

O legal que o próprio instalador já te diz o que foi feito e os próximos passos pra rodar a aplicação. Notem que ele mostrou toda a estrutura de diretório e arquivos criados, e deixou claro que você precisa instalar as dependências com “npm install”, antes de rodar o projeto. Então faça isso:

$ cd web
$ npm install
<dezenas de linhas omitidas>
[email protected] node_modules/express
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] ([email protected])
├── [email protected] ([email protected])
└── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected])

[email protected] node_modules/jade
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] ([email protected], [email protected], [email protected])
├── [email protected] ([email protected])
├── [email protected] ([email protected])
└── [email protected] ([email protected])

Quais dependências foram instaladas? E onde? E de onde elas vieram? Vou dar uma dica, olhe o arquivo package.json. Ele define os metadados so seu projeto, incluindo as dependências:

$ cat package.json 
{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.0",
    "jade": "*"
  }
}

Viu que o express e o jade são listados como dependências (já falamos falar do jade)? É por isso que eles foram instalados com o “npm install”. Sempre que o “npm install” roda sem nenhum argumento adicional ele procura o arquivo package.json, e instala as dependências listadas lá. Para entender melhor a estrutura desse arquivo veja na documentação do Node e do NPM, que é muito bem feita.

O NPM sempre instala as dependências em um subdiretório do diretório onde o package.json está, chamado “node_modules”. Essa é a estrutura do meu diretório “node_modules”:

$ ll node_modules/
drwxrwxr-x 2 giovanni giovanni 4096 Sep 19 09:16 .bin/
drwxrwxr-x 5 giovanni giovanni 4096 Sep 19 09:16 express/
drwxrwxr-x 5 giovanni giovanni 4096 Sep 19 09:16 jade/

Veja os diretórios do jade e do express instalados. E veja que há um diretório “.bin”. Esse diretório contém os executáveis dos módulos. Veja o que eles tem:

$ ll node_modules/.bin
lrwxrwxrwx 1 giovanni giovanni   22 Sep 19 09:16 express -> ../express/bin/express*
lrwxrwxrwx 1 giovanni giovanni   16 Sep 19 09:16 jade -> ../jade/bin/jade*

O Express e o Jade expõe ferramentas de linha de comando. O mesmo “express” que usamos pra criar o projeto está agora também sob o diretório “node_modules/.bin/express”. Isso deixa esses executáveis com fácil acesso.

Com tudo instalado, basta rodar o projeto. E isso é fácil, quando criamos o projeto ele já nos indicou como fazer isso, basta executar “node app”:

$ node app
Express server listening on port 3000

Navegue para http://localhost:3000 e você verá sua aplicação no ar:

Express rodando

Conforme você acessa o projeto, o Express vai logando o que ele está servindo:

Express logando o que está servindo

Para parar o projeto mande um Control-C no terminal.

Essa página inicial é bem simples. De onde ela vem? Não vou contar agora, vou deixar pro próximo post. Por enquanto, veja a estrutura final do diretório “web”:

$ tree -I node_modules
.
├── app.js
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│   └── style.css
├── routes
│   ├── index.js
│   └── user.js
└── views
    ├── index.jade
    └── layout.jade

6 directories, 7 files

E veja o conteúdo do arquivo app.js:

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Já dá pra ter uma ideia certo? Experimente com ele, veja o que descobre. Eu volto em breve pra explicar mais do Express e do Jade, além de outros componentes importantíssimos que estão nessa stack.