Installer et utiliser Node.js sous Windows

Je vous propose à travers cet article de découvrir Node.js pour le système d'exploitation Windows 7, 8 et 10. Node.js est multi-plateforme et s'exécute tout aussi bien sous Unix que sous Mac. Mais QUID de Windows ? Vous allez voir que c'est assez trivial même si certains modules dépendent de quelques logiciels externes pour compiler (python27, msvc2013). Assez rapidement donc, il vous sera possible de développer des sites web et applications web très interactives et avec une grande vélocité d'exécution le tout avec JavaScript !

Télécharger Node.js pour Windows

Je passe les présentations qui ont déjà été faites dans cet article et ajoute que même si cet article a été réalisé avec des tests parallèles sous Seven, je ne vois pas pourquoi il ne serait pas valable pour Windows 8 ou 10.

Le site officiel de Node.js

Site du projet : nodejs.org.

Le logo Node.js

Avant de nous jeter sur la partie « Downloads », jetons un œil aux parties du site que je ne vais pas détailler plus dans cet article. Vous pourrez apprendre à l'accueil (Home) que Microsoft, Google, Yahoo!, LinkedIn, Ebay... et bien d'autres utilisent d'ores et déjà Node.js, découvrir le projet dans About et le suivre avec le Node.js Blog ainsi que la Community. Vous pourrez même trouver du travail dans la partie Jobs. Pour finir un jolie fond d'écran traine sur la page Logos.

Intaller node et npm

Depuis l'accueil, vous devriez voir un bouton « Download for Windows (x64) » (si vous êtes sur Windows). Cliquez dessus pour télécharger automatiquement le zip le plus adapté à votre système. Vous pouvez également choisir vous même votre zip dans Download pour obtenir au choix le Windows Installer (.msi) et/ou le Windows Binary (.exe) en 32/64 bit.

Liste des composants de l'installeur Node.js
Liste des composants de l'installeur Node.js

Exécutez votre fichier, acceptez la licence, déposez-le dans "Program files" et ce package va vous installer :

  • L'exécuteur node.js : le programme permettant d'exécuter des fichiers .js (comme php.exe le ferait avec des .php).
  • Le module npm (Node Package Manager) : un gestionnaire de modules qui va vous permettre simplement d'ajouter et retirer les librairies dont vous aurez besoin pour vos applications (pas de surplus, seulement le nécessaire donc).
  • Un raccourci vers la documentation en ligne.
  • Des variables d'environnements : Ainsi vous pourrez exécuter les commandes node et npm dans votre invité de commande.
Dossier de Node.js après installation
Dossier de Node.js après installation

Quand l'installeur aura fini vous aurez un joli dossier d'environ 12Mo contenant entre autre node.js et npm.cmd qui seront appelables depuis n'importe quel dossier avec les commandes node et npm.

Un Hello world en Node.js

Juste après l'installation, tentons notre premier « Hello World ». Tout d'abord, définissez vous un endroit ou installer vos projets Node.js. Pour ma part j'ai décidé de placer tous mes projets dans C:\nodejs. Je vais donc y créer un fichier hello-world.js accessible à cette adresse sur mon poste : C:\nodejs\hello-world.js. Rien ne vous empêche de placer ça dans un autre dossier, sur un autre disque dur, dans le workspace de votre IDE ou le repository de votre logiciel de gestion de code source et version.

Édition de hello-world.js

Faisons la chose la plus simple possible, affichons un message dans une console d'exécution. Ouvrez le fichier C:\nodejs\hello-world.js que vous venez de créer avec Nodepad++ ou Sublime Text 3 (ou l'IDE de votre choix) et copier/coller à l'intérieur le code suivant :

console.log("Hello World !"); // Va écrire dans la console "Hello World !".

global.console.log("Hello World !"); // Va écrire dans la console "Hello World !".

window.console.log("Hello World !"); // Va faire planter le programme.

puis sauvegardé le.

Exécution de script avec node.exe

Il y a plusieurs façons d'appeler du code JavaScript avec le programme node.exe.

Tout d'abord :

  • appuyez/cliquez sur la touche/bouton « Logo Windows » ce qui ouvrira votre « Menu Démarrer » ou vos tuiles,
  • écrivez directement cmd ici et cela se tapera dans une barre de recherche,
  • enfin, appuyez sur la touche « Entrer » pour ouvrir votre Console.

Ensuite deux possibilités.

Exécution en absolue

  • Écrivez node C:\nodejs\hello-world.js (dans la console) puis appuyez sur « Entrer » pour exécuter le script,
  • ou écrivez node C:\nodejs\hello-world (pas d'extension).

Exécution en relatif

  • Écrivez cd C:\nodejs\ puis appuyez sur « Entrer » pour vous rendre dans le dossier,
  • écrivez node hello-world.js puis appuyez sur « Entrer » pour exécuter le script,
  • ou node hello-world (pas d'extension).
Résultat d'exécution du fichier C:\nodejs\hello-world.js
Résultat d'exécution du fichier C:\nodejs\hello-world.js

L'équivalent de window est global

Notre code plante et c'est normal ! Revenons sur le résultat obtenu (image ci-avant) et voyons se que l'on peut en déduire.

  • Les commandes global.console.log et console.log sont identiques. La base global est donc implicite comme window.document et document dans les navigateurs.
  • La pile d'exécution nous indique qu'au lancement de node.exe, avant même le traitement du fichier en paramètre, il y a :

    • Lecture du fichier node.js et exécution de startup.
    • Lecture du fichier module.js exécutant la fonction Function.Module.runMain exécutant la fonction Function.Module._load exécutant la fonction Module.load exécutant la fonction Object.Module._extensions..js exécutant la fonction Module._compile. Or, il n'y a pas de fichier node.js ou module.js dans le dossier de node.exe. Ce traitement est donc réalisé par le cœur de Node.js, node.exe.
  • window n'est pas défini. Il est de type Undefined et renvoi "undefined" puisqu'il fait planter le script. global remplace donc window en Node.js.

La documentation, les modules et le principe

Effectivement, notre exemple précédent est loin de servir à quelque chose et même loin de nous permettre de développer un site Internet (mais pas si loin que ça tout de même). Faisons quelque chose de plus conséquent.

Et si nous utilisions un bout de code qui va nous permettre de parcourir l'intégralité d'une arborescence de fichier/dossier de manière asynchrone et de lever des événements à chaque fois que quelque chose est parcouru.

Nous allons manipuler le contenu d'un dossier avec le code ci-après. Pour le moment, nous allons nous attacher à la syntaxe du langage.

// Déclaration de plusieurs variables.
var
    fs = require("fs"), // Instanciation du module natif "File System" dans la variable "fs".
    walk = require("walk"), // Instanciation du module communautaire "node-walk" dans la variable "walk".
    files = [], // Instanciation d'un tableau vide dans la variable "files".
    targetFolder = process.argv[2] || "./", // Instanciation d'une variable avec "process.argv[2]". Si process.argv[2] est de type Undefined alors il renvoi "false" et targetFolder vaut "./";.

    // Appel à la fonction "walk" du module "walk".
    walker = walk.walk(
        targetFolder, // Passage d'une "String" en premier paramètre.
        { followLinks: false } // Passage d'un "Objet" JSON en second paramètre.
    );

    /* Equivalant du code ci-dessus
    var walk = require("walk");
    var files = [];
    var walker = walk.wa....;
    mais moins performant. */

// Appel à la fonction "on" du module "walk".
walker.on("file", function(root, stat, next) { // "String" en premier paramètre et "Function" en second paramettre.
    // Ajout d'une entrée dans le tableau "files".
    files.push(root + stat.name);

    // Exécution du paramètre "next" de type "Function".
    next();
});

/* En javascript, les paramètres peuvent être également des fonctions !
La fonction de walk "on" est probablement défini ainsi : 
function on(String, Function) {
    var 
        root = String,
        stat = ** infos sur le fichier **
        next = function () { ** du code ** }

    Function(root, stat, next);
}
*/

// Appel à la fonction "end" du module "on".
walker.on("end", function() {
    // On affiche le contenu du tableau dans la console Windows.
    console.log(files);
});

// Affichage de "Traitement en cours..." dans l'invité de commande Windows (la console).
console.log("Traitement en cours...");

Le code ci-dessus permet d'afficher tous les fichiers d'un dossier. Si vous êtes familier avec JavaScript il ne vous aura pas échappé que la fonction require sort d'un chapeau magique. C'est une fonction spécifique à Node.js qui permet d'inclure des fonctions en provenance d'un autre fichier (en l’occurrence du cœur de Node.js pour « File System » et du module node-walk pour « walk ».

Compiler les modules qui ne sont pas en JavaScript sous Windows

Si vous souhaiter pouvoir utiliser l'intégralité des modules de Node.js il va falloir être en mesure de tous les compiler. Effectivement, la majorité des modules sont écrit en JavaScript et Node.js sait très bien les utiliser. Mais pour ceux qui sont écrit dans un autre langage (pas en JavaScript), voici les deux logiciels qui peuvent couvrir tous les cas de figure : installer Python et Microsoft Visual Studio.

La documentation de Node.js et de ses modules

Le cœur de Node.js contient les modules vitaux lui permettant d'écrire dans des fichiers. C'est au développeur, en fonction de ses besoins, de « télécharger » les modules complémentaires qu'y vont lui permettre de réaliser ses développements.

Documentation des modules natifs

La documentation des modules natifs de Node.js se trouve sur le site officiel dans la partie Documentation. Vous pourrez vous renseigner sur le fonctionnement des modules incontournables comme « File System » ou encore « http » (pour faire des serveurs web). Vous aurez également des information sur notre fameuse fonction require

Documentation des modules tiers

Tout un chacun peut développer son propre module Node.js et le mettre à disposition des autres utilisateurs via GitHub et à disposition en téléchargement via le NPM de Node.js en l'ajoutant au registre de la page NPM Registry.

Par exemple, pour ma part, je développe NodeAtlas qui est un module permettant de créer rapidement de petit site web MVC2, de créer des gros sites interactif ou encore gérer des maquettes HTML.

C'est également le cas du module node-walk qui ajoute la fonction walk équivalente à la fonction du même nom en Python mais pour Node.js. Ce module est utilisé dans le code précédent et développé par l'utilisateur coolaj86. La documentation de node-walk se trouve donc sur la page de son projet GitHub et son module est référencé dans le registre NPM sur cette page.

En se référent à sa documentation, nous sommes à même de comprendre le code précédent :

var
    fs = require("fs"),
    walk = require("walk"),
    files = [],
    // Récupération du premier paramètre derrière le nom du fichier, sinon dossier d'exécution du fichier.
    targetFolder = process.argv[2] || "./",

    // La fonction walk permet de lire de manière asynchrone le contenu d'un fichier mais ne renvoi rien. 
    // Le code du script va continué à être lu pendant que walk va faire son boulot.
    walker = walk.walk(targetFolder, { followLinks: false }); // L'option dit qu'on ne va pas lire les fichiers derrière les raccourcis de dossier.

// La fonction "on" avec en premier paramètre "file" est exécuté quand la fonction assynchrone précédente "walk" lit un fichier.
walker.on("file", function(root, stat, next) {
    //... et le paramètre "root" contient le chemin absolue du fichier.
    //... et le paramètre "stat" contient diverses informations comme le "name" du fichier.
    //... et le paramètre "next" est en réalité une function.
    files.push(root + stat.name);

    // Différent traitement avec fs (suppression, copy, etc...) sont possible.

    // On valide les actions.
    next();
});

// La fonction "on" avec en premier paramètre "end" est exécuté quand tout le contenu du répertoire à été lu.
walker.on("end", function() {
    console.log(files);
});

// Va être lu immédiatement après l'exécution de la fonction "walk".
// Si votre walk lit le dossier "C:\", cela preut prendre du temps de tout lire. Mais il ne sera pas bloqué car les fonctions dans "on" sont appelés de façon assynchrone.
console.log("Traitement en cours...");

npm et le téléchargement de modules

Téléchargement depuis le registre

Copiez-collez le code précédent dans un fichier appelé list-file.js (par exemple dans C:\nodejs\routine\list-file.js) et exécutez-le.

Résultat d'exécution du fichier C:\nodejs\routine\list-file.js
Résultat d'exécution du fichier C:\nodejs\routine\list-file.js

Notre code plante encore et c'est encore normal ! Revenons sur le résultat obtenu (image ci-avant) et voyons ce que l'on peut en déduire.

  • L'exécution de ce script est identique au précédent, mais la pile ne s'affiche pas complètement (manque startup et node.js).
  • Quand la fonction require est rencontrée, à l'instar de startup c'est require qui prend la main exécutant la fonction Function.Module._load exécutant la fonction Function.Module._resolveFilename.
  • Si un module n'a pas été préalablement téléchargé, ça coince (logique).

Note : les scripts qui plantent arrête le programme Node.js. Si votre script ne plante pas, et que vous souhaitez arrêter le programme : au lieu de fermer la console, appuyez simultanément sur « CTRL + C ».

Nous allons donc télécharger le module « node-walk » avec les lignes de commande suivante :

  • cd C:\nodejs\routine\
  • npm install walk
Téléchargement du module node-walk avec npm
Téléchargement du module node-walk avec npm

Vous constaterez qu'un dossier « node_modules » est apparu. Les futurs modules que vous téléchargerez via npm depuis la racine C:\nodejs\routine\ seront automatiquement ajoutés dans ce dossier. Les fichiers dont le fichier appelant est exécuté dans cette racine pourront tous bénéficier des modules via la commande « require » directement avec le nom du module en paramètre. Pour utiliser le module d'un autre dossier « node_modules », il ne faudra plus passer le nom du module à require mais le chemin d'accès. Pour finir si vous utilisez la commande npm install depuis un autre dossier, les modules téléchargés se mettront dans le dossier « node_modules » de cet endroit (ou le créera s'il n'existe pas).

Votre dossier « node_modules » contient le module « walk ». Vous constatez que « walk » lui-même contient un dossier « node_modules » avec le module « forEachAsync » ! C'est une dépendance du module : « walk » à besoin de « forEachAsync » pour fonctionner. Idem dans « forEachAsync » il y a encore un dossier « node_modules » contenant « sequence ».

Note : vous pouvez également passer l'option -g soit npm install -g walk qui installera walk dans le node_modules global. Vos projets n'auront alors pas besoin d'avoir walk dans leur dossier « node_modules » pour fonctionner.

Vous pouvez de nouveau exécuter votre script et constater que "Traitement en cours..." s'écrit avant l'affichage des fichiers alors que c'est pourtant la dernière instruction du fichier. Là est le pouvoir de l'asynchrone !

*Note : vous pouvez passer des paramètres à vos scripts avec process.args[x] x représentant le xième élément séparé par un espace dans la chaine de commande (process.args[0] étant donc le mot node). Dans notre exemple node list-file C:\ affichera les fichiers de tout le disque dure !

Téléchargement depuis le site du module

Dans notre exemple précédent nous aurions tout aussi bien pu créer nous-même le dossier « node_modules » et y placer le module node-walk à la main en l'ayant téléchargé depuis le site GitHub.

Si vous voulez essayer, effacez votre dossier « walk » de « node_modules » et c'est parti !

  • Une fois sur la page du projet, cliquez sur « ZIP » pour télécharger l'archive.
  • Placer le dossier « node-walk-master » dans « node_modules » et renommez-le en « walk ».
  • Dans votre nouveau dossier « walk », supprimez tout sauf le dossier « lib ».
  • Remontez le contenu du dossier « lib » dans « walk ». Vous pouvez maintenant supprimer le dossier « lib » qui est vide.
  • Exécutez de nouveau list-file et vous aurez l'erreur « Error: cannot find module 'forEachAsync' » (souvenez vous, « walk » dépend de « forEachAsync »).
  • Rendez-vous sur le NPM registry et cherchez « forEachAsync » dans « Search Packages ». Cliquez dessus dans la liste et repérez la ligne « Dependencies » : vous voyez bien que ce module est dépendant de « sequence ». Repérez ensuite « Homepage » : cliquez sur le lien associé et nous revoilà sur Git. Cliquez de nouveau sur « ZIP » pour télécharger l'archive. Nous trouvons dedans, entre autre, les dossiers « forEachAsync » et « sequence » ! Ça tombe bien.
  • Créez dans « walk » un dossier « node_modules » pour y placer « forEachAsync », puis dans « forEachAsync » vous créez de nouveau un dossier « node_modules » pour y placer « sequence ».
  • Exécutez de nouveau list-file et voilà, ça marche !

Cette technique à vite ses limites pour les gros modules.

Node.js pour créer des routines

Pour clore cet article je résumerais en mettant en avant le fait que sans même parler de site Internet, Node.js est parfais pour créer des fichiers de maintenance pour effacer des fichiers temporaires, exécuter des actions, etc... comme le ferait des fichiers .php avec php.exe. Il est tout à fait possible de mettre en place des tâches planifiées pour vider les fichiers de plus de un jour dans le répertoire temporaire des fichiers uploadés de votre site par exemple !

Bon, maintenant qu'on voit à peut-prêt l'outil pour une utilisation standard et simple, si on faisait des sites web avec le module NodeAtlas !