Depuis plusieurs mois, Triotech participe depuis Montpellier (Sud de la France) au développement de node.ci, une plateforme proposant l’intégration continue de projets utilisant la technologie Node.js. Son fondateur et dirigeant, Eric Burin des Roziers, nous présente les différents aspects de ce nouveau langage, qui a déjà été adopté par de grands groupes tels que Paypal.
53% du trafic de walmart.com est desservi par Node.js; les applications mobiles linkedin.com sont supportées par Node.js avec des performances exceptionnelles; en 2013, Groupon repense son architecture pour des raisons de performance et de rapidité de développement en adoptant Node.js, remplaçant Ruby; en 2012, Node.js devient le langage de programmation le plus populaire sur Github.com; Joyent et Strongloop (8 M$ de levée de fonds en 2013 – équivalent à 5,8 M€) proposant des solutions de support en production pour Node.js.
Node.js n’est pas seulement un nouvel environnement de développement ou la dernière mode, mais plutôt un changement profond de programmer le server-side en utilisant des évènements.
– Joyent engineering VP, Bryan Cantrill
Qu’est ce que Node.js exactement pour que cela suscite autant de bouleversement dans la façon de développer le server-side ? En très bref, Node.js est simplement l’utilisation du langage de programmation javascript du coté serveur.
Javascript, créé en 1994 par Netscape, est un langage interprété (non pas compilé comme l’est C++) conçu pour tourner sur un navigateur et pour être simple afin d’attirer des non-développeurs ou « amateurs ». Javascript connut une période de mauvaise réputation et de confusion. Son nom, proche de java, fut probablement l’un des principaux facteurs de confusion. « car » et « carpet » ont les même similarité que « java » et « Javascript », dit-on sur StackOverflow. Les développeurs professionnels dénigrent le langage, le considérant comme trop basic et fait pour les novices. Puis, ECMAScript, un organisme de standardisation de javascript, fut formé en 1997. Mais, ce n’est pas avant le début des années 2000, avec la sortie de Ajax, que les développeurs professionnels commencèrent à prendre ce langage plus sérieusement.
Un petit aparté : Ajax fut la clef de voûte du mouvement web 2.0. Cette technologie permettra de rafraîchir une sous-partie d’une page web sans avoir à recharger toute la page. Une nouvelle expérience utilisateur fut donc possible dans le navigateur, une expérience plus proche de celles des applications ‘desktop’. Javascript fut rapidement le langage de programmation le plus utilisé dans le monde.
Pour mieux comprendre la révolution Node.js, Il y a trois propriétés importantes de Javascript à mettre en avant (event-driven, non-blocking, et single-threaded) :
Ces trois éléments, indispensables pour la programmation d’un IHM n’étaient jusqu’à présent pas utilisés du coté serveur qui utilisait massivement les « threads », chacun d’eux bloquant sur leurs requêtes I/O avec pas (ou très peu) d’évènements.
Voilà qu’en 2009, Ryan Dahl créa Node.js, mettant le moteur Javascript V8 du navigateur Google Chrome en tant que serveur d’application Javascript. Cette technologie, idéale pour les applications exigeant un grand nombre de petits évènements, tel qu’une application mobile avec ses multiples requêtes pour des données de petites tailles, prit rapidement de l’envergure dans la communauté de startups de la Silicon Valley. Le JSON, un format plus compact que le XML, fut un catalyseur de ce mouvement. Le langage de programmation le plus populaire fait alors ses débuts du coté serveur et verra en 2013 une popularité dépassant les autres langages interprétés du server-side, tel que Ruby et PHP.
De son histoire, Javascript n’a jamais vraiment complètement surmonté sa réputation de ‘sous-langage’, malgré les progrès avancés par les différents navigateurs avec leur promesse du HTML 5. De nombreux critiques avancent des problèmes de performance, de manque de structure et de difficulté de maintenance (non-compilable, pas object-oriented, et not typed.) Voici les points fort de Node.js, réfutant certaines de ses critiques :
Javascript est un langage interprété (scripting language), c’est-à-dire non-compilé ou pas transformé en ‘instruction’ machine (binaire) qui peut être directement exécuté par le processeur. Javascript a donc besoin d’un moteur (interpréteur) qui lit et convertit le code en ‘instruction’ directement pendant son exécution. Cela rend l’évaluation plus lente, mais a pour avantage de pouvoir être modifiée ou créée en ‘run-time’, c’est-à-dire pendant son évaluation. Cependant, les performances de Node.js, du fait de son architecture d’évènement, sont excellentes ! Attention, Node.js est idéal pour des requêtes nécessitant peu de calcul en mémoire et gérant des données de relativement petite taille. Toute application ayant besoin de calcul intensif ne devrait pas utiliser Node.js. Cependant, il est très facile d’appeler des modules C/C++ à partir de Node.js, permettant d’utiliser la rapidité de Node.js et la puissance de calcul de C/C++.
Contrairement à d’autres langages tels que Ruby et Java, Node.js est son propre serveur HTTP. Cependant, il est déconseillé de servir du contenu statique par Node.js pour des raisons de performance : nginx, un serveur HTTP ultra-performant et très léger est préférable. Tout contenu dynamique, par contre, est servi par Node.js. Le fait que Node.js soit son propre serveur HTTP apporte des avantages considérables, laissant Node.js contrôler toute la logique du serveur HTTP, absence de configuration Apache séparée du code de l’application, par exemple.
Avec plus de 53.000 modules Node.js open source, npm (https://www.npmjs.com/), le répertoire de module open source Node.js, compte en moyenne plus d’un million de téléchargements par jour. Beaucoup de ces modules sont créés et maintenus par des entreprises telles que Joyent, Zendesk, LearnBoost et Visionmedia. Un projet Node.js reste typiquement de petite taille. Ainsi, une application Node.js se compose alors de plusieurs modules. Cet aspect permet une haute maintenabilité et de pouvoir distribuer plus facilement le développement.
Le code de validation de champs est un exemple flagrant de réutilisation nécessaire du code.
Aujourd’hui, tout est développé à travers des services ou API. Pour autant, le navigateur (comprendre le client) est lui aussi responsable de certaines tâches, telles que la validation des champs de saisies. Il existe de multiples clients différents, n’ayant pas forcement les mêmes quantité de ressources disponibles, notamment lors de l’utilisation de tablettes et/ou téléphones. Ce n’est donc pas pour autant que le serveur ne devrait pas non plus corriger et/ou valider ces champs. Le partage du code de validation entre les clients et le serveur réduit le coût de développement et de maintenance. D’autres exemples existent, tels que les modules utilitaires (underscore.js).
Les closures, des fonctions encapsulées dans une autre ayant accès au contexte de son parent, et les lambdas, des fonctions anonymes, font parties des principes qui rendent le Javascript, et par extension, Node.js, très puissante, flexible et maintenable. Ces concepts rendent la nature asynchrone de Node.js (et Javascript) facile à manipuler. Il est possible de définir une fonction sans la nommer et la passer en tant que ‘callback’ dans une autre fonction asynchrone. Cette fonction anonyme sera alors évaluée quand la fonction asynchrone aura terminé sa tâche, en passant bien sûr par le bus d’évènement.
La « pyramide de la mort » (pyramide of doom) est un terme que les sceptiques lancent à tour de bras. Il s’agit de fonctions lambdas imbriquées les unes dans les autres, rendant le code difficile à lire et à maintenir.
functionA(function(data) { functionB(function(data2) { functionC(function(data3) { functionD(function(data4) { functionE(function(data5) { //Votre code }) }) }) }) })
Ce problème est celui d’un débutant et il y a plusieurs manières de le résoudre. Les ‘promises’ sont les plus élégantes. Une ‘promise’ est un objet qui implémente la méthode ‘then()’ qui sera appelée lors du retour de l’appel asynchrone. Avec ce mécanisme, le code devient plus simple, facile à lire et à maintenir :
functionA() .then(functionB(data1) .then(functionC(data2) .then(functionD(data3) .then(functionE(data4)
Il existe plusieurs modules facilitant l’utilisation des promises, notamment ‘Promise’ (https://github.com/then/promise) ou ‘Q’ (https://github.com/kriskowal/q). Vous pourrez trouver plus d’information sur ce site consacré aux promises JavaScript : https://www.promisejs.org/.
Le problème de [scaling] est un problème très difficile à résoudre, indépendamment du langage utilisé. Il n’y a malheureusement pas de recette à suivre et la solution dépend du type d’application, des caractéristiques des données, des profils utilisateurs et souvent nécessite des compromis et refactoring fréquents. Néanmoins, il existe des lignes directrices et meilleures pratiques basées sur les expériences de la communauté de développeurs.
C’est un sujet vaste et passionnant sur lequel beaucoup peut être dit et débattu. Mais, voici un aperçu rapide classé en trois aspects complémentaires. (1) des recommandations générales s’appliquant à chaque instance Node.js ; (2) une approche verticale utilisant la fonctionnalité Node.js de ‘child process’ ou le module ‘cluster’ de LearnBoost; et (3) une approche horizontale utilisant la base de données RedisStore et les web socket (socket.io).
Node.js n’est pas (encore) un leader mais promet d’être une technologie avec énormément de potentiel. L’utilisation de Node.js a triplé en 1 an, selon w3techs, et est le leader sur les sites à très haut trafic.
Enfin, Node.js s’insère aussi dans l’innovation qu’est l’Internet des objets, ou objets connectés car elle y est idéale et davantage d’outils, d’applications et de modules Node.js sont développés. Tessel.io est un exemple de technologie utilisant les avantages de Node.js permettant de facilement connecter du hardware au Web. Beagle Board et Rasberry Pi ont eux aussi des modules Node.js. Des myriades de projets mariant le hardware et Node.js sont publiés sur le Web.
Node.js est en pleine croissance et n’a pas encore atteint son apogée. StrongLoop a parié 8M$ en 2013 (soit 5,8 M€) justement sur cette croissance dans le mobile. Nodejitsu, Heroku, Amazon et Microsoft Azure (et d’autre encore) soutiennent tous Node.js. Il y a encore beaucoup à faire avec de grosses possibilités d’innovation.
Node.js est une marque déposée de Joyent, Inc. Tous droits réservés.