Node.js, le pavé dans la mare
DekNOD v1.0.0
Un exemple, vite !
http://tweetping.net/
2
1. Présentation de Node
Qu'est-ce que Node
Projet créé en 2009 par Ryan Dahl (Joyent Inc.)
Basé sur le langage JavaScript
Sur-couche de Chrome V8
Positionné côté serveur
Piloté par les événements
4
GitHub : Node sur le podium
5
Ceux qui l'utilisent
6
Objectifs de Node
Fournir une pile logicielle permettant :
Aux développeurs web : JavaScript / navigateur
De développer des serveurs
Faciliter les fonctionnalités de push
Proposer une API d'I/O suffisament bas niveau
Privilégier les appels non bloquants
7
Chrome V8
Moteur JavaScript open source
Utilisé dans les navigateurs (Google Chrome)
Ou en standalone (Node)
Compile le JavaScript en code natif
Optimise à la volée :
Inlining
Cache
Garbage collector
8
Architecture
9
Chaîne de traitement
10
2. Fonctionnalités
Gestionnaire de packages NPM
NPM : Node Packages Modules
Gère les dépendances d'une application Node
Déclarées dans package.json
Dépôt local dans node_modules/ (cf. NODE_PATH)
Un peu comme Maven...
npm install : télécharge les dépendances
npm publish : publie un module dans le dépôt central
Scopes : local au projet, ou global
12
Modèle asynchrone vs multi-thread
13
Modèle asynchrone - impacts dans le code
// Synchrone function loadData(id) { var data = store.find(id); return data; } var result = loadData(3); console.log('result :', result); console.log('continue...');
// Asynchrone function loadData(id, callback) { store.find(id, function(data) { callback(data); }); } loadData(3, function(result) { console.log('result :', result); }); console.log('continue...');
14
Synchrone – moins gentil function manageRequest(request) { var product, model, view, content; product = store.find(id); if (product === null) { content = renderer.render('notFound.html'); return content; } model = { id:product._id, name:product.name, price:product.price }; view = 'productDetail.html'; content = renderer.render(view, model); if (content === null) { return renderer.render('internalError.html'); } return content; } response.write(manageRequest(request));
15
Asynchrone – moins gentil function manageRequest(request, callback) { var product, model, view, content; store.find(id, function (product, err) { if (err) { content = renderer.render('notFound.html', function (content) { callback(content); }); return; } model = { id:product._id, name:product.name, price:product.price }; view = 'productDetail.html'; content = renderer.render(view, model, function (content, err) { if (err) { renderer.render('internalError.html', function (content) { callback(content); }); return; } callback(content); }); }); } manageRequest(request, function (content) { response.write(content); });
16
Because nothing blocks, less-than-expert programmers are able to develop fast systems
nodejs.org/about
17
3. Modules standards
Net, Http
Net permet d'agir au niveau socket
En tant que serveur ou client
Avec des méthodes de base
Et des événements à écouter : connect, data, end, close
Http : idem mais au niveau web
S'appuie sur Net et l'interface générique EventEmitter
Supporte SSL
19
Os, Process, Child process
Os : informations relatives au système d'exploitation
Type, plateforme, mémoire, cpus, interfaces réseaux
Pas l'habitude d'avoir accès à ces infos ☺
Process : informations du processus
Arguments, environnement, propriétaire, entrées sorties standards
Child process : gestion de processus
Exec, fork, spawn
20
Path , File System
Path : outils pour travailler sur les chemins de fichiers ☹ var monfic = 'mondir/sousdir/name.ext' ☺ var monfic = path.join('mondir', 'sousdir', 'name.ext')
File System :
Opérations sur les fichiers : ●
Lecture répertoire, suppression, écriture, information, liens symboliques
APIs synchrones ou asynchrones
21
Modules
Node fournit quelques variables globales
module, process, mais pas window
Et un mécanisme pour rendre les choses modulaires
Inspiration pythonesque ☺
module.exports = { foo: function(){ return 'bar'; } };
var myModule = require('./lib/mymodule'); myModule.foo();
/app.js /lib/mymodule.js
22
4. Modules tiers
Les incontournables – module async
forEach, filter, map, log
nombreux helpers pour la gestion asynchrone
var async = require('async'); async.forEach(['a', 'b', 'c'], function (item, callback) { if (item === 'b') { callback(new Error('b forbidden')); } else { console.log(item); callback(); } }, function (err) { if (err) { console.log('Error :', err); } else { console.log('done'); } });
Résultat : a Error : [Error: b forbidden] c
Résultat avec forEachSeries : a Error : [Error: b forbidden]
24
Asynchrone multi steps – à la main
step1(params, function (result) { step2(result, function () { step3(result, function () { step4(result, function () { fini(); }); }); }); });
25
Asynchrone multi steps – pattern / module Step
step1(params, function (result) { var n = 0; var next = function () { n++; if (n === 3) { fini(); } }; step2(result, next); step3(result, next); step4(result, next); });
Step( function () { step1(params, this); }, function (result) { step2(result, this.parallel()); step3(result, this.parallel()); step4(result, this.parallel()); }, function () { fini(); } );
26
Les incontournables – module commander
Pour exposer des commandes
Plus pratique qu'une gestion avec process.argv commander .version(version) .option('-f, --force', 'force on non-empty directory') .option('-r, --refresh', 'refresh files') ... .parse(process.argv); appPath = commander.args.shift() || process.cwd(); if (commander.force) { force(); ... } 27
Les incontournables – module Express
Framework pour application web Node :
Minimaliste et flexible
Basé sur le middleware connect
Définition de routes sophistiquées
Injection de moteur de rendu : jade, ejs, consolidate var express = require('express'); var app = express(); app.get('/hello.txt', function(req, res){ res.send('Hello World'); }); app.listen(3000); 28
Les incontournables – module i18n
Module de traduction léger
Stockage en json
Facilité d'intégration avec Express var express = require('express') , i18n = require('i18n'); i18n.configure({ locales:['en', 'fr'], register: global }); app.locals({ __: i18n.__, __n: i18n.__n }); app.configure(function() { app.use(i18n.init); ... }); var welcome = __('Welcome');
29
Les incontournables – module mongoose
API mongodb pour Node :
Adaptée au côté asynchrone de Node
Convient à de nombreuses situations : local, distant, cloud
var mongoose = require('mongoose') , db = require('./db'); var contactDao = { entityName:'contact', schema:mongoose.Schema({ firstName:{ type:String }, lastName:{ type:String }, phoneNumber:{ type:String } }), getModel:function () { return db.connection.model(contactDao.entityName, contactDao.schema) } };
30
Simple db helper
var mongoose = require('mongoose') , db = { connection:null, connect:function () { db.connection = mongoose.connect('mongodb://localhost:27017/db'); }, close:function () { if (db.connection !== null) { mongoose.disconnect(); db.connection = null; return true; } return false; } }; db.connect(); process.on('exit', function (code) { var result = db.close(); console.log('disconnecting db : ', result); });
31
Les incontournables – module socket.io
Pour jouer avec les web sockets
Modes dégradés pour les navigateurs
Ajax, Adobe Flash Socket, iframe
Facilité d'intégration avec Express
var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) { socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); });
<script src="/socket.io/socket.io.js"> <script> var socket = io.connect('http://localhost'); socket.on('news', function (data) { console.log(data); socket.emit('my other event', { my: 'data' }); });
serveur
client 32
5. Développement JavaScript
IDE et debug
La qualité de l'offre des IDEs est limitée
Langage non typé, trop dynamique
Eclipse : top avec Java, bof avec JS
Faire sans :
Faire avec :
On se contente d'un éditeur (vi, textmate, ...), parfois amélioré
Le choix du moment : WebStorm (Jetbrains)
Mode Debug (si vraiment nécessaire ☺) :
En ligne de commande (à-la-gdb)
Dans WebStorm : plus confortable
34
Monter en compétence sur JavaScript
Résister aux tentations
Se concentrer sur le meilleur
Et sur le résultat obtenu
JavaScript Koans :
Inspiré de Ruby
35
6. Usine Logicielle
Les composantes essentielles d'une Usine
Qualité du code : jslint, jshint
Tests unitaires : mocha, qunit, jstd, jasmine, maven
Couverture du code : jscoverage, coverjs
Minifiers et autres compilateurs : less, coffee script, ...
Outil de build : grunt
Solutions efficaces pour chaque besoin
Pas toujours pour l'ensemble...
37
Déploiement & clouds
Déployer une application Node :
En standalone
Derrière un front
Pourquoi pas un front Node...
Cloud :
Heroku, Nojitsu, AppFog, ...
38
7. Code Kata
Web live chat
8. Exemples et retours d'expérience
Node en synthèse
Node réinvente les roues des frameworks web
Un environnement auto-suffisant et très typé
Le JavaScript en réponse à tous les besoins
41
Node en synthèse (suite)
Node impose un modèle non bloquant / mono thread :
Adapté aux applications réseaux légères et rapides
Solution de choix pour une application web :
Dont la compléxité est surtout côté client
Un éco-système très prolifique
Mais jeune...
42
9. Questions / Réponses
Notre offre JavaScript
Développement client avec JavaScript et Ajax
Développement JavaScript avancé
réf. JAJA – 2 jours
Développer une application Web Full JavaScript
réf. JASI – 3 jours
réf. STAX – 4 jours
Programmer avec jQuery
réf. RESI – 2 jours
44