Retour aux sources

On l'oublie souvent, mais au moment de sa conception en 1995 par Brendan Eich pour le compte de Netscape, JavaScript a d'abord été un langage pour le serveur, avant de rapidement intégrer le navigateur. Netscape a longtemps essayé de défendre cette utilisation, avant qu'elle ne disparaisse peu à peu.

Langage maudit du Web 1 (à cause des implémentations incompatibles de Navigator et d'IE qui obligeaient à développer le code en double), JavaScript a peu à peu gagné ses lettres de noblesse avec le Web 2, DHTML et AJAX, et les nombreuses bibliothèques qui ont permis de faire abstraction des spécificités des navigateurs. Depuis environ deux ans, les principaux fondeurs de navigateur se livrent à une compétition forcenée autour de JS, et les performances des moteurs ont explosé (en 10 ans, elles auraient été multipliées par presque 100[1]). Aujourd'hui, il devient par exemple de plus en plus envisageable d'avoir dans le navigateur, propulsées par JavaScript, des applications demandant de la puissance de calcul, comme par exemple de la 3D. Et l'utilisation de JavaScript sur le serveur revient au goût du jour, les performances du langage commençant à rivaliser avec celles des autres. Signes de ce retour, le grand nombre de bibliothèques "serveur" qui fleurissent depuis quelques mois, et surtout le projet CommonJS.

Mais pour quoi faire ?

L'intérêt de permettre à JavaScript d'enfin s'ébattre sur le serveur me semble évident. Utiliser le même langage sur le client et le serveur présente plusieurs avantages:

  • actuellement, développer une application Web demande de connaître au moins deux langages, l'un sur le serveur, l'autre dans le navigateur[2] et des langages assez différents, car JavaScript, ne serait-ce que par son implémentation particulière du modèle objet, a une logique bien spécifique. J'ai toujours trouvé fatigant, dans un projet Web, de devoir passer sans arrêt de JavaScript à PHP/Python/Java/Ruby/..., parce que les philosophies sont différentes, et accessoirement certaines petites différence de syntaxe sont propices aux erreurs. Les fréquents sauts d'un langage à l'autre empêchent de se mettre en mode automatique et fatiguent;
  • de nombreuses opérations (des validations de données saisies par exemple) doivent être codées deux fois, dans deux langages, avec des implémentations le plus proches possibles. En se limitant à un seul langage, on peut réutiliser davantage de code, avoir la garantie qu'il n'y a pas de différence d'implémentation d'un algorithme entre le client et le serveur (ce qui est toujours la cause de soucis difficilement détectables). On diminue ainsi la charge de travail, et accélère le développement.
  • la communication entre le client et le serveur s'en trouve facilitée, puisqu'on est sûr que les données sont encodées et décodées de la même façon;

Plusieurs projets relativement pionniers expérimentent déjà ce type d'architecture. Par exemple Jaxer, un projet libre développé depuis plusieurs années par Aptana. Jaxer utilise Gecko sur le serveur, c'est à dire à la fois le moteur JavaScript, SpiderMonkey, et toutes les bibliothèques incluses dans Firefox pour manipuler du XML, le DOM, les accès au système de fichier, etc. Parallèlement Aptana a également créé ActiveJS, un ensemble de bibliothèques utilisables aussi bien dans le navigateur que sur le serveur, et facilitant la mise en œuvre de MVC en JavaScript pur. Parmi les autres précurseurs, on pourra également regarder du côté d'Helma ou de Haxe.

CommonJs

Une des principales raisons pour moi du succès de PHP est la grande richesse de bibliothèques disponibles dans le cœur du projet ou à proximité (c'est à dire dans PEAR ou PECL). Quoi que l'on veuille faire, on trouvera une bibliothèque facile à installer et relativement bien documentée.

JavaScript à l'opposé est un langage que je trouve plus puissant que PHP (il est par exemple réellement objet et offre depuis longtemps des mécanismes qui arrivent timidement dans les dernière versions de l'éléphant bleu), mais pauvre en bibliothèques. Hormis la manipulation du DOM, plus récemment un peu de dessin avec les travaux sur Canvas, on est assez frustré dès que l'on veut l'utiliser pour faire autre chose que que rendre dynamique une page Web. C'est possible, mais encore faut-il trouver les bibliothèques qui vont bien et espérer qu'elles soient compatibles avec le moteur qu'on utilise. Ayant effectué l'essentiel de sa croissance au sein du navigateur, le langage a beaucoup de mal à couper le cordon et s'en émanciper, alors qu'il en aurait le potentiel. C'est pourtant un langage de script moderne qui, du strict point de vue du langage, n'a pas grand chose à envier à PHP, Python, Ruby, etc. Sa faiblesse majeure est dans la pauvreté actuelle de son écosytème, sur le serveur du moins.

Kevin Dangoor, qui travaille sur les outils pour les développeurs chez Mozilla, a remis sur le tapis l'utilisation de JavaScript sur le serveur dans un excellent billet au début de l'année, qui a depuis été suivi de nombreux autres allant dans le même sens. What Server Side JavaScript needs détaille les faiblesses actuelles de JavaScript et l'intérêt d'y remédier pour qu'il prenne enfin son envol sur le serveur. Lancé sous le nom de ServerJS, un groupe de discussion a rapidement eu un gros succès, et a donné naissance au projet CommonJS.

L'objet du projet est de définir un socle d'APIs permettant de répondre aux problématiques les plus courantes, pour que JavaScript dispose enfin des bibliothèques qui lui font tant défaut. La tâche est ardue, car si le cœur de JavaScript est standardisé par l'ECMA, les nombreuses implémentations de la spécification ont parfois pris des libertés avec elle, et surtout ont pallié ses manques en implémentant chacun sa solution. Les problèmes de compatibilité du code sont donc nombreux, et les bibliothèques implémentant CommonJS devront fonctionner de façon transparente avec tous les moteurs disponibles (cf une liste plus bas). Mais elles offriront ainsi un socle sur lequel on pourra s'appuyer pour enfin créer des applications de plus haut niveau, comme jQuery, Prototype et compagnie ont permis de s'abstraire des soucis de compatibilité pour se concentrer sur le développement.

Une version 0.1 de la spécification a déjà vu le jour qui définit l'API de modules inter-opérables, pour pouvoir facilement charger des bibliotèques externes et les faire communiquer entre elles. La version 0.5 en cours de développement crée quatre autres API : pour la manipulation d'objets binaires, l'accès à un système de fichiers, les tests unitaires, et la communication avec les serveurs Web (JavaScript Gateway Interface - JSGI). De nombreuses autres sont en cours de discussion sur le wiki et la liste de discussion. Plusieurs projets ont d'ors et déjà entrepris d'implémenter la spécification, l'un des plus avancés étant sans doute Narwal.

Effervescence

Le regain d'intérêt pour l'utilisation de JavaScript sur le serveur est aussi manifeste par le nombre de projets qui ont éclos ces derniers mois. La liste est longue, en voici quelques uns parmi ceux que je trouve les plus prometteurs:

  • Narwhal est un ensemble de bibliothèques JS conformes à CommonJS. Le projet aspire à être indépendant du moteur. Narwhal sert entre autre de base à Jack, une couche permettant la communication entre des applications JavaScript s'exécutant sur un serveur, et un serveur Web. Jack implémente la spécification JSGI, développée pour l'occasion, qui définie une API pour ces communications. JSGI s'inspire des spécification WSGI en Python et Rack en Ruby;
  • Persevere est un serveur permettant entre autre de stocker des objets JavaScript et d'y accéder directement via des services REST. Il est développé par l'équipe de Dojo et en particulier par Kris Zyp dont j'ai déjà parlé dans mes billets sur JSON. Grâce à CommonJS, Narwhal et Persevere peuvent à présent être utilisés de concert, au travers de l'API de modules;
  • Helma NG (Next Generation) est un framework JavaScript serveur écrit en Java et basé sur Rhino. Sa nouvelle version (NG) vise à le simplifier et à implémenter CommonJS;
  • Node est un serveur écrit en JavaScript et utilisant le moteur V8. Il propose une implémentation de serveur alternative à celle habituelle basée sur des threads. Il s'inspire par exemple de Twisted en Python. S'il n'implémente pas encore CommonJS, c'est un bel exemple de l'intérêt d'utiliser JS sur le serveur;

Mis à jour j'oubliais que JavaScript est aussi le langage invité de nouvelles bases de données comme CouchDB, où il est utilisé pour faire des requêtes complexes. Il commence donc même à se faire sa place dans le domaine des bases de données.

Quoi d'autre ?

Dernier point, j'ai parlé jusqu'à présent d'unification du langage utilisé dans le client et sur le serveur, mais il y a un troisième acteur à prendre en compte: la plate-forme, en l'occurrence le navigateur. Personne n'ignore que JavaScript est utilisé intensivement dans Firefox, et tout particulièrement dans les extensions. Une position qui va encore gagner en importance avec l'arrivée de JetPack, la nouvelle architecture pour les extensions, dont le slogan est si tu sais créer une appli Web, tu sais aussi créer une extension. Pour ce que j'en ai vu, les extensions Chrome vont elles aussi utiliser JS. CommonJS a donc également une indéniable utilité à ce niveau, en permettant de créer des composants génériques qui seront également utilisables par la plate-forme, le navigateur, et portables d'un navigateur à l'autre. A terme, cela facilitera sans doute encore les interactions entre le navigateur et les contenus.

Ces nouveaux horizons qui s'ouvrent à JavaScript me plaisent beaucoup. Vu la vitesse à laquelle les différents projets avancent, on devrait voir des trucs assez sympas arriver dans les prochains mois.

Annexe : tour d'horizon des moteurs

A ce jour, les moteurs libres les plus répandus et qui peuvent être utilisés sur le serveur, sont

  • SpiderMonkey : inventé par Brendan Eich en même temps que JavaScript, il est aujourd'hui maintenu par Mozilla. Il évolue aujourd'hui sous le nom de TraceMonkey en intégrant des bouts de Tamarin, un projet commun à Mozilla et Adobe. SpiderMonkey étant codé en C, il offre des mécanismes pour utiliser des routines écrites en C ou C++. C'est ainsi que dans Firefox, composants en C++ et modules en JavaScript travaillent de concert;
  • Rhino est un moteur en Java développé par Mozilla. Il offre aussi des passerelles avec Java. On peut ainsi appeler des bibliothèques Java depuis le code JavaScript, ou utiliser Rhino dans un projet Java ayant besoin de fonctions de scripting;
  • v8 de Google, probablement le plus véloce actuellement;
  • SquirrelFish utilisé dans Safari. mise à jour on me glisse en commentaire que 4D, éditeur d'une fameuse base de données sur Mac, travaille sur le projet Wakanda qui l'utilisera;
  • je ne parle pas des moteurs utilisés dans Opéra ni IE car je ne sais pas s'ils existent en tant que projets indépendants du navigateur. Ils ne sont de toute façon à ma connaissance pas libres;
  • pour aller plus loin, Wikipédia propose une liste plus complète de moteurs;

Notes

[1] référence nécessaire, j'ai vu ça dans une graphique sur un site de développeur Google, mais sans source et je ne le retrouve même plus. Si vous avez des infos...

[2] je n'ai pas encore testé les solutions qui génèrent automatiquement le code client depuis le langage serveur, comme Google Web Toolkit par exemple, j'avoue qu'elles m'attirent moins