Am besten beginne ich dort, an der Norbert seinen Beitrag mit einen Link auf einen einfachen Node.js TCP Server beendet hat. Mein Wunsch war eine Implementierung eines einfachen Chats mit einer netten Benachrichtungsfunktion im MacOS Growl Stil.
Da ich möglichst schnell erste Ergebnisse sehen wollte, bin ich diesen Weg der Ubuntu Package Manager Installation für Node.js v0.4.9 gegangen.
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
Danach folgte die Installation von Express.js, EJS und Socket.IO mit Hilfe des Node Package Manager (NPM).
npm install -g express
npm install ejs
npm install socket.io
Bei Express.js handelt es sich um eine Ruby on Rails inspirierte Implementierung eines MVC Web Framework Stacks inkl. Request/Response Routing, Template Engine und Middleware zur einfachen und schnellen Erstellung von flexiblen und performaten Web Sites und RESTful Services.
EJs ist eine in Express.js eingebettete View Template Engine zur dynamischen Generierung von HTML Web Sites.
Ich verwende Socket.IO zur Implementierung von bidirektionaler Clientbenachrichtigungen (Push-Kommunikation) über den Browser. Socket.IO abstrahiert verschiedene Formen der bidirektionalen Kommunikation zwischen Client und Server. Dazu bedient sich Socket.IO, wenn möglich HTML5 WebSockets, oder eines Flash Plugin's oder, sollte keine bidirektionale Kommunikation möglich sein, auch dem Ajax Polling.
Wie beginnen wir mit der Implementierung der Chat-App mit Node.js und Express.js?
Als erstes erstellen wir einen Web Application Skeleton unter der Verwendung der EJs Template Engine mit
mkdir FooBar & cd FooBar
und dem Kommando
express -t ejs
Danach lösen wir die Express.js dependencies über
npm install -d
Und fertig ist die erste "Default"-Web Anwendung. Gestartet wird die Anwendung per
node app.js
und ist unter http://localhost:3000 zu erreichen.
Express.js generiert dabei folgende Anwendungsstruktur
app.js | zentrales Anwendungsprogramm |
node_modules | Node.js und Express.js Module Dependencies |
package.json | Anwendungsbeschreibungsdatei |
public | Inhaltsablage (assets) für JavaScript, Bilder, StyleSheets |
views | Ablage für HTML-Templates |
Jetzt benötigen wir noch Socket.IO. Diese installieren wir über
npm install socket.io
Um Growl Benachrichtigungen anzeigen zu können, laden uns wir uns jGrowl über
curl -o public/javascripts/jquery.jgrowl_1.zip http://plugins.jquery.com/files/jquery.jgrowl_1.zip
unzip public/javascripts/jquery.jgrowl_1.zip -d public/javascripts/
Nun erstellen wir eine neue Template Datei mit
touch views/sample.ejs
vi views/sample.ejs
<!DOCTYPE html> <head> <title><%= title %></title> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript">google.load("jquery", "1.4.4");</script> <script type="text/javascript" src="/socket.io/socket.io.js"></script> <script type="text/javascript" src="/javascripts/jgrowl/jquery.jgrowl.js"></script> <link rel="stylesheet" href="/javascripts/jgrowl/jquery.jgrowl.css" type="text/css" /> <script type="text/javascript">var port = <%= port %>;</script> <script type="text/javascript" src="/javascripts/client.js"></script> </head> <body> <form action="" id="form"> <input type="text" name="message" id="message" /> <input type="submit" value="Nachricht senden" /> </form> <div>Verlauf:</div> <hr /> <dl id="list"></dl> </body> </html>
Nun registrieren wir die neue Url-Route zur views/sample.ejs in der app.js mit
app.get('/sample', function(req, res){ res.render('sample', { title: 'Welcome to growl sample app', port: 3000, layout: false }); });
Mit dieser Anweisung wird Express.js angewiesem, auf der angeforderten Resource http://localhost:3000/sample das EJd Template sample.ejs zu rendern und auszuliefern.
Nun erstellen wir das notwendige Client side JavaScript zur Kommunikation mit dem Node.js Server.
touch public/javascripts/client.js
vi public/javascripts/client.js
$(function() { $.jGrowl.defaults.pool = 5; var socket = io.connect(); socket.on('connect', function() { console.log('connect'); }); socket.on('message', function(msg) { console.log(msg); var now = new Date(); $.jGrowl(msg, { sticky: false, header: now.toLocaleString(), life: 10000 }); $('#list').prepend($('<dt>' + now.toLocaleString() + '</dt><dd>' + msg + '</dd>')); }); socket.on('disconnect', function(){ console.log('disconnect'); }); $('#form').submit(function() { var message = $('#message'); socket.send(message.val()); message.attr('value', ''); return false; }); });
Im nächsten Schritt müssen wir die Socket.IO Event-Handler zur Nachrichtenkommunikation in unserer Anwendung registrieren. Dies geschieht mit folgenden Snippet.
var io = require('socket.io').listen(app); io.sockets.on('connection', function(client) { console.log('connected'); client.send('hi...'); client.broadcast.send('... new client connected.'); client.on('message', function(msg) { console.log(msg); client.send(msg); client.broadcast.send(msg); }); client.on('disconnect', function() { console.log('disconnect'); }); });
Der spannende Teil ist vorallem
client.on('message', function(msg) {
...
client.broadcast.send(msg); ...
});
Mit diesem Callback werden alle registrierten Clients beim Empfang einer Client-Nachricht auf Server-Seite mit einer Broadcast-Nachricht über die Änderung benachrichtigt. Die Benachrichtigung wird über die Implementierung in der /public/javascripts/client.js Datei einmal in eine Liste geschrieben und zweitens über die jGrowl Anweisung
$.jGrowl(msg, { sticky: false, header: now.toLocaleString(), life: 10000 });
in die Growl Pipeline geschrieben. Schön finde ich, dass Socket.IO Nachrichten nur an die anderen Empfänger sendet und nicht an den ursprünglichen Absender. Mit
client.send(msg);
ist es möglich, die gesendete Nachricht auch an den Sender zurück zu senden.
Insgesamt sieht die app.js jetzt so
var express = require('express'); var app = module.exports = express.createServer(); app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public')); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Routes app.get('/', function(req, res){ res.render('index', { title: 'Express' }); }); app.get('/sample', function(req, res){ res.render('sample', { title: 'Welcome to growl sample app', port: 3000, layout: false }); }); app.listen(3000); var io = require('socket.io').listen(app); io.sockets.on('connection', function(client) { console.log('connected'); client.send('hi...'); client.broadcast.send('... new client connected.'); client.on('message', function(msg) { console.log(msg); client.send(msg); client.broadcast.send(msg); }); client.on('disconnect', function() { console.log('disconnect'); }); }); console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
Abschließend starten wir die Anwendung mitnode app.js
und sollten dann mit folgendem Screen belohnt werden.
Verbunden mit mehreren Web-Browser Clients ist nun ein minimaler Chat mit Growl-Nachrichten möglich.
Und auch im iPhone, iPad oder Windows Phone 7 macht Node.js, Socket.IO und jGrowl eine gute Figur.
Ich hoffe dieser kleine Einblick in die Welt von Node.js und JavaScript macht Lust auf mehr. Meine Implementierung könnt ihr euch gern unter
http://beta2.mikebild.com:3000/sample
ansehen.
Keine Kommentare:
Kommentar veröffentlichen