Express per Node.js
Il modo migliore per scrivere applicazioni web per Node.js è quello di utilizzare un framework come Express.
Come sempre con i nuovi framework bisogna capire come iniziare. Per questo ci viene in aiuto express-generator che crea una strutttura base di un applicazione.
Prima di tutto va installato express-generator quindi apri la command line di node:
a questo punto puoi creare l'applicazione, posizionati in una directory e digita:
questo comando crea una directory sgartapp con la seguente struttura:
fatto questo, quello che manca è express e le sue dipendenze. Per installarle digita:
per vedere l'applicazione apri il browser su http://localhost:3000
o http://localhost:3000/users.
Express implementa il pattern MVC dove sotto /routes abbiamo i controlles mentre le view sono sotto /views.
Guardando nel dettaglio i singoli file dell'applicazione, il file /bin/www rappresenta l'istanza del webserver:
l'entry point dell'applicazione express è rappresentato dal file /app.js:
Il controller /routes/index.js contiene:
la corrispondente view /views/index.jade contiene:
ad esempio per usare ejs
e la view diventa
con codice html in stile asp classic.
Come sempre con i nuovi framework bisogna capire come iniziare. Per questo ci viene in aiuto express-generator che crea una strutttura base di un applicazione.
Prima di tutto va installato express-generator quindi apri la command line di node:
DOS / Batch file
npm install -g express-generator
DOS / Batch file
express sgartapp
DOS / Batch file
/
+-- app.js
+-- bin
| +-- www
+-- package.json
+-- public
| +-- images
| +-- javascripts
| +-- stylesheets
| +--- style.css
+-- routes
| +-- index.js
| +-- users.js
+-- views
+-- error.jade
+-- index.jade
+-- layout.jade
DOS / Batch file
cd sgartapp && npm install
Il comando npm install si occupa di scaricare i pacchetti da internet e e ogni pacchetto viene posizionato in una cartella sotto /node_modules. Per trovare l'elenco dei file da scaricare npm si basa sul file package.json. All'interno del file, nella sezione dependencies, sono riportati tutti package necessari con le relative versioni.
a questo punto per eseguirlo:DOS / Batch file
SET DEBUG=sgartapp:* & npm start
npm start esegue l'applicazione basandosi sul file package.json più precisamente la sezione scripts/start che è impostata a node ./bin/www
Questo è un esempio di file package.json:JavaScript
{
"name": "sgartapp",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.1",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "~2.3.2",
"express": "~4.13.0",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0"
}
}
Guardando nel dettaglio i singoli file dell'applicazione, il file /bin/www rappresenta l'istanza del webserver:
JavaScript
#!/usr/bin/env node
// moduli dipendenze
var app = require('../app');
var debug = require('debug')('sgartapp:server');
var http = require('http');
// imposta la porta su cui è in ascolto, se non indicata
// nella variabile di ambiente PORT, usa la 3000
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
// crea il server HTTP con il file /app.js che usa express
var server = http.createServer(app);
// mette il server in ascolto sulla porta indicata
// su tutte le interfaccie
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
// normalizza la porta in un numero, stringa o false
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
// gestore dell`evento errori HTTP
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
// gestore dell'evento HTTP "listening"
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
JavaScript
//carico i moduli necessari
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//carico i moduli dell`applicazione (non va indicata l`estensione .js)
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// imposta l`engine delle view e il path (/views)
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// da decomentare se si mette la favicon.ico in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//imposta la directory /public come static ovvero non gestita da express,
// ritorna i file così come sono anche i .js
app.use(express.static(path.join(__dirname, 'public')));
//inposta i path (routes) gestiti dell`applicazione
app.use('/', routes); //mappo il controller /routes/index.js sulla root /
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// gestori errori
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
JavaScript
var express = require('express');
var router = express.Router();
/* implemento il metodo GET che ritorna la home page */
router.get('/', function(req, res, next) {
//passo alla view /views/index.jade un oggetto (model)
res.render('index', { title: 'Express' });
});
module.exports = router;
Text
extends layout
block content
h1= title
p Welcome to #{title}
di default express usa come template engine jade
In fase di creazione dell'applicazione è possibile usare altri template engine per le view. Per vedere quali engine sono supportati digita express -h:DOS / Batch file
C:\node>express -h
Usage: express [options] [dir]
Options:
-h, --help output usage information
-V, --version output the version number
-e, --ejs add ejs engine support (defaults to jade)
--hbs add handlebars engine support
-H, --hogan add hogan.js engine support
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sas
s) (defaults to plain css)
--git add .gitignore
-f, --force force on non-empty directory
DOS / Batch file
express --ejs sgartapp
HTML
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
</html>