« Node.js » : différence entre les versions
(62 versions intermédiaires par 12 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
{{ | {{tutoriel | ||
|fait_partie_du_cours=Initiation à la pensée computationnelle avec JavaScript | |||
|fait_partie_du_module=JavaScript sur le serveur | |||
|module_précédant=JavaScript dans le navigateur | |||
|module_suivant=JavaScript dans d'autres environnements | |||
|pas_afficher_sous-page=Non | |||
|page_precedente=JavaScript sur le serveur | |||
|page_suivante=Express.js | |||
|statut=à finaliser | |||
|difficulté=avancé | |||
|cat tutoriels=JavaScript | |||
}} | |||
==Introduction== | ==Introduction== | ||
[https://nodejs.org/ Node.js] ( | [https://nodejs.org/ Node.js] (aussi abrégé "Node" par la suite) est un interprète du langage JavaScript, qui permet d’utiliser JavaScript en dehors des navigateurs web, notamment du « côté-serveur », les desktops ou les « embedded devices ». Les caractéristiques principales de Node concernent le fonctionnement basé sur les événements et l’architecture « non-blocking » des mécanismes d’input/output (I/O). Grâce à ces particularités, Node est surtout utilisé dans le développement d’applications web « scalables », c’est-à-dire qui permettent de moduler les ressources hardware nécessaires en fonction du nombre d’utilisateurs et/ou de la puissance de calcul. | ||
===Objectifs de cette page=== | ===Objectifs de cette page=== | ||
Cette page a | Cette page a comme objectif pédagogique la sensibilisation de l’utilisation de [[JavaScript]] dans d’autres environnements que le navigateur web. Elle ne propose donc pas l’illustration exhaustive des caractéristiques techniques de Node.js. '''Les concepts et exemples illustrés sont donc limités à des environnements de test et/ou contrôlés par les développeurs et ne doivent pas être utilisés dans des situations où la fiabilité et la sécurité sont primordiales.''' | ||
Pour comprendre le contenu de cette page la | Pour comprendre le contenu de cette page, la connaissance des pages suivantes est conseillée : | ||
* [[Introduction à la programmation]] | * [[Introduction à la programmation]] | ||
* [[JavaScript]] | * [[JavaScript]] | ||
Ligne 12 : | Ligne 22 : | ||
===Avertissement de sécurité=== | ===Avertissement de sécurité=== | ||
Contrairement à JavaScript côté-client dont l’exécution est contrôlée/limitée par les navigateurs web, Node.js peut avoir accès au système d’exploitation sur lequel il est installé. Ceci signifie que si vous installez Node.js sur votre ordinateur, Node.js peut potentiellement interagir avec | [[Fichier:Warning.png|100px|gauche|]] | ||
Contrairement à JavaScript côté-client, dont l’exécution est contrôlée/limitée par les navigateurs web, Node.js peut avoir accès au système d’exploitation sur lequel il est installé. Ceci signifie que si vous installez Node.js sur votre ordinateur, Node.js peut potentiellement interagir avec les fichiers du système. | |||
'''Il faut donc faire beaucoup plus attention avec Node.js par rapport à JavaScript côté-client, même en phase de développement/test ! Il y a un risque de corrompre ou effacer des fichiers importants, même au niveau du fonctionnement du système !''' | |||
===L’écosystème Node.js=== | ===L’écosystème Node.js=== | ||
Ligne 19 : | Ligne 32 : | ||
* Lire/Écrire des fichiers | * Lire/Écrire des fichiers | ||
* Accéder et/ou manipuler des bases de données | * Accéder et/ou manipuler des bases de données | ||
* Créer des applications réseaux comme des | * Créer des applications réseaux comme des serveurs web ou des streaming audio/vidéo | ||
* Etc. | * Etc. | ||
Pour obtenir cela, Node.js met à disposition des développeurs des « modules » qui sont déjà disponibles avec l’interprète ou qui peuvent être gérés grâce à [https://www.npmjs.com/ npm], un gestionnaire de bibliothèques installé automatiquement avec Node.js. Ce gestionnaire permet d’ajouter facilement des « extensions » qui peuvent être téléchargées et utilisées : | Pour obtenir cela, Node.js met à disposition des développeurs des « modules », qui sont déjà disponibles avec l’interprète ou qui peuvent être gérés grâce à [https://www.npmjs.com/ npm], un gestionnaire de bibliothèques installé automatiquement avec Node.js. Ce gestionnaire permet d’ajouter facilement des « extensions » qui peuvent être téléchargées et utilisées : | ||
# Dans des applications Node (e.g. [ | # Dans des applications Node (e.g. [[Express.js]] ou [[Electron]]) | ||
# En tant qu’outils pour effectuer des tâches liées au développement telles que des tests (e.g. [https:// | # En tant qu’outils pour effectuer des tâches liées au développement telles que des tests (e.g. [https://jestjs.io/en/ Jest]), gestions de bibliothèques JavaScript et/ou CSS (exemple : [https://gruntjs.com/ GruntJS]), génération de squelettes pour applications (e.g. [https://www.npmjs.com/package/yo yeoman]), etc. | ||
===Quelques mots sur la ligne de commande=== | ===Quelques mots sur la ligne de commande=== | ||
Pour utiliser Node.js il faut | Pour utiliser Node.js, il faut très souvent utiliser la [[wp_fr:Interface_en_ligne_de_commande|ligne de commande]]. Il y a différentes possibilités pour ouvrir une ligne de commande et cela dépend notamment du système d’exploitation utilisé, mais les commandes illustrées par la suite devraient marcher dans toutes lignes de commande. Voici une liste de logiciels de ligne de commande pour les principaux systèmes d’exploitation : | ||
* Pour Windows utiliser [https://fr.wikipedia.org/wiki/Windows_PowerShell Windows PowerShell] | * Pour Windows utiliser [https://fr.wikipedia.org/wiki/Windows_PowerShell Windows PowerShell] | ||
* Pour Mac utiliser le [http://www.osxfacile.com/terminal.html Terminal] | * Pour Mac utiliser le [http://www.osxfacile.com/terminal.html Terminal] | ||
* Pour Linux utiliser l’une des lignes de commandes disponibles selon la version. | * Pour Linux utiliser l’une des lignes de commandes disponibles selon la version. | ||
====Position dans l’arborescence du système==== | ====Position dans l’arborescence du système==== | ||
Lorsque vous utilisez la ligne de commande de votre ordinateur il faut être très | Lorsque vous utilisez la ligne de commande de votre ordinateur, il faut être très attentif au dossier dans lequel vous vous trouvez, car c’est au niveau de ce dossier que vont s’exécuter les éventuelles actions d’Input/Output générées par Node. L'adresse du dossier dans lequel vous vous trouvez s’affiche normalement sur la gauche de votre ligne de commande, sinon elle peut être récupérée avec la commande <code>pwd</code>. | ||
[[Fichier:Node.js command position actuelle.png|none|thumb|600x600px|Toujours bien vérifier la position actuelle (i.e. le path) lorsqu'on utilise la ligne de commande. ]] | [[Fichier:Node.js command position actuelle.png|none|thumb|600x600px|Toujours bien vérifier la position actuelle (i.e. le path) lorsqu'on utilise la ligne de commande. ]] | ||
====Références relatives dans les dossiers==== | |||
Vous pouvez faire référence aux différents niveaux de l'arborescence par rapport à la position actuelle avec les notations suivantes : | |||
* <code>./</code> fait référence au dossier actuel | |||
** '''attention''' à ne pas confondre avec <code>/</code> (sans point) qui fait référence à la '''racine de votre système''' où se trouvent des fichiers importants ! | |||
* <code>../</code> fait référence à un niveau supérieur | |||
* <code>../../</code> fait référence à deux niveaux supérieurs | |||
* etc. | |||
====Quelques commandes de gestion de fichiers en ligne de commande==== | ====Quelques commandes de gestion de fichiers en ligne de commande==== | ||
Vous pouvez également « naviguer » à travers les dossiers directement à l’intérieur de la ligne de commande, ainsi qu’obtenir des informations sur le contenu du dossier. | Vous pouvez également « naviguer » à travers les dossiers directement à l’intérieur de la ligne de commande, ainsi qu’obtenir des informations sur le contenu du dossier. | ||
Avec la commande <code>cd</code> vous pouvez vous déplacer dans d’autres | Avec la commande <code>cd</code> vous pouvez vous déplacer dans d’autres dossiers avec des adresses relatives ou absolues : | ||
* <code>cd Documents</code> se déplace dans un dossier « Documents » contenu à l’intérieur de la position actuelle | * <code>cd Documents</code> se déplace dans un dossier « Documents » contenu à l’intérieur de la position actuelle | ||
*<code>cd ../</code> se déplace à un niveau supérieur par rapport à la position actuelle | ** Cela équivaut à <code>cd ./Documents</code> | ||
* <code>cd C:/Users/votrelogin/Music</code> se déplace dans la position absolue du dossier Music | * <code>cd ../</code> se déplace à un niveau supérieur par rapport à la position actuelle | ||
* <code>cd C:/Users/votrelogin/Music</code> se déplace dans la position absolue du dossier Music | |||
'''Évitez de travailler en ligne de commande dans des dossiers de système de votre système d’exploitation (e.g. C:/Windows/System) ou directement dans des dossiers racines comme par exemple le dossier C:/ | '''Évitez de travailler en ligne de commande dans des dossiers de système de votre système d’exploitation (e.g. C:/Windows/System) ou directement dans des dossiers racines comme par exemple le dossier C:/ de Windows.''' Il est fortement conseillé de travailler dans des sous-dossiers créés exprès pour tester des scripts Node.js. | ||
Pour vous orienter dans les chemins de vos dossiers, vous pouvez lire le contenu d’un dossier avec la commande <code>ls</code> qui affiche tous les fichiers et | Pour vous orienter dans les chemins de vos dossiers, vous pouvez lire le contenu d’un dossier avec la commande <code>ls</code> qui affiche tous les fichiers et dossiers contenus dans la position actuelle. | ||
De plus, vous pouvez également utiliser des commandes pour créer, renommer ou effacer des dossiers ou des fichiers directement en ligne de commande. Ces commandes ne sont pas l’objet de cette page, donc on se limitera à l’exemple de la commande <code>mkdir</code> qui permet de créer un nouveau dossier : | De plus, vous pouvez également utiliser des commandes pour créer, renommer ou effacer des dossiers ou des fichiers directement en ligne de commande. Ces commandes ne sont pas l’objet de cette page, donc on se limitera à l’exemple de la commande <code>mkdir</code> qui permet de créer un nouveau dossier : | ||
Ligne 57 : | Ligne 81 : | ||
==Installation de Node.js== | ==Installation de Node.js== | ||
L’installation de Node | L’installation de Node pour, des finalités de développement et de test, est très simple, mais plus complexe – ou du moins pour le moment (novembre 2015) – pour les environnements de production, qui ne seront pas traités dans cette page. | ||
Node.js est disponible à travers le [http://nodejs.org site officiel]. Le | Node.js est disponible à travers le [http://nodejs.org site officiel]. Le téléchargement est disponible sur la page d’accueil, qui suggère directement la version adaptée à l’ordinateur de l’utilisateur, ou dans la page « Downloads » qui permet de choisir parmi les différentes versions disponibles. | ||
[[Fichier:Node.js site installation.png|none|thumb|500x500px|Download de Node.js depuis la page d'accueil du site officiel]] | [[Fichier:Node.js site installation.png|none|thumb|500x500px|Download de Node.js depuis la page d'accueil du site officiel]] | ||
Node est disponible pour Windows, Mac et Linux, ainsi que d’autres systèmes. Pour les systèmes Windows et Mac, Node met à disposition des versions avec « installer » qui représente la manière la plus simple pour ajouter Node à votre ordinateur. Il faut choisir : | Node est disponible pour Windows, Mac et Linux, ainsi que d’autres systèmes. Pour les systèmes Windows et Mac, Node met à disposition des versions avec « installer », ce qui représente la manière la plus simple pour ajouter Node à votre ordinateur. Il faut choisir : | ||
* La version Windows Installer, avec extension .msi, pour Windows | * La version Windows Installer, avec extension .msi, pour Windows | ||
* La version Macintosh Installer, avec extension .pkg, pour Mac | * La version Macintosh Installer, avec extension .pkg, pour Mac | ||
Ensuite, il suffit de suivre les étapes du programme d’installation. Les réglages suggérés sont adaptés pour la plupart des | Ensuite, il suffit de suivre les étapes du programme d’installation. Les réglages suggérés sont adaptés pour la plupart des besoins, il ne faut donc normalement pas faire de changements. Pour les installations Windows, il faut juste être attentif à la nécessité d’ajouter Node.js au PATH afin que la commande « node » soit disponible partout dans le système. Cette option est automatiquement cochée dans les réglages suggérés, il faut donc éviter de la décocher : | ||
[[Fichier:Node.js installation path.png|none|thumb|600x600px|Pour les utilisateurs Windows, laisser l'option Add to PATH cochée. ]] | [[Fichier:Node.js installation path.png|none|thumb|600x600px|Pour les utilisateurs Windows, laisser l'option Add to PATH cochée. ]] | ||
De plus, à partir de la version <code>10.x.x</code>, le script d'installation propose également d'installer d'autres éléments pour compiler. Il s'agit de composantes très lourdes et qui ne servent pas dans la plupart de cas. '''Il est donc mieux d'éviter de cocher la case, à moins que l'on sache vraiment ce que l'on fait !''' | |||
===La commande node=== | ===La commande node=== | ||
Pour contrôler que Node a bien été installé, ouvrez la ligne de commande (voir plus haut dans la page) et tapez directement le code : | Pour contrôler que Node a bien été installé, ouvrez la ligne de commande (voir plus haut dans la page) et tapez directement le code : | ||
node -v | node -v | ||
La version installée de Node.js devrait s’afficher sur la ligne de commande. Voici le résultat pour la Windows PowerShell avec Node.js version 4.2.2. Faites attention avec Linux parce que | La version installée de Node.js devrait s’afficher sur la ligne de commande. Voici le résultat pour la Windows PowerShell avec Node.js version 4.2.2. Faites attention avec Linux parce qu'il arrive parfois que la commande associée ne soit pas node mais bien nodejs. | ||
[[Fichier:Node.js check version.png|none|thumb|600x600px|Pour contrôler l'installation de Node.js, saisir la commande node -v en ligne de commande. ]] | [[Fichier:Node.js check version.png|none|thumb|600x600px|Pour contrôler l'installation de Node.js, saisir la commande node -v en ligne de commande. ]] | ||
Ligne 82 : | Ligne 108 : | ||
# Évaluer (i.e. Eval) les expressions | # Évaluer (i.e. Eval) les expressions | ||
# Afficher (i.e. Print) le résultat | # Afficher (i.e. Print) le résultat | ||
Vous pouvez donc saisir directement des commandes JavaScript dans la ligne de commande après le <code>></code> : | Vous pouvez donc saisir directement des commandes JavaScript dans la ligne de commande après le chevron <code>></code> : | ||
[[Fichier:Node.js command repl.png|none|thumb|600x600px|Exemple de code JavaScript en ligne de commande après la commande node. ]] | [[Fichier:Node.js command repl.png|none|thumb|600x600px|Exemple de code JavaScript en ligne de commande après la commande node. ]] | ||
Pour sortir de la modalité console de Node.js tapez deux fois sur <code>Ctrl + C</code>. Cette commande est utile pour sortir de | Pour sortir de la modalité console de Node.js tapez deux fois sur <code>Ctrl + C</code>. Cette commande est utile pour sortir de toutes les opérations en ligne de commande en général. Notez également que <code>Ctrl + C</code> ne permet pas de copier du texte surligné dans la ligne de commande. Utilisez le clic droit pour copier et coller du texte. | ||
[[Fichier:Node.js command quit.png|none|thumb|600x600px|Pour sortir de la console REPL tapez deux fois sur CTRL + C. ]] | [[Fichier:Node.js command quit.png|none|thumb|600x600px|Pour sortir de la console REPL tapez deux fois sur CTRL + C. ]] | ||
====Exécuter le code dans un fichier JavaScript==== | ====Exécuter le code dans un fichier JavaScript==== | ||
La commande <code>node</code> accepte également un ou plusieurs arguments, dont le premier | La commande <code>node</code> accepte également un ou plusieurs arguments, dont le premier fait référence à un fichier.js contenant du code, alors que les suivants sont des arguments qui sont passés au script : | ||
node [fichier.js] [arg1, arg2, …] | node [fichier.js] [arg1, arg2, …] | ||
Pour essayer vous pouvez créer un fichier script.js dans un dossier avec le simple code suivant : | Pour essayer vous pouvez créer un fichier script.js dans un dossier avec le simple code suivant : | ||
Ligne 113 : | Ligne 139 : | ||
===La commande npm=== | ===La commande npm=== | ||
La commande <code>npm</code> peut être utilisée pour plusieurs finalités qui vont au-delà des objectifs de cette page. Pour l’occasion, nous limiterons son intérêt à la fonction d’installation des modules Node.js. L’installation peut se faire à deux niveaux : | La commande <code>npm</code> peut être utilisée pour plusieurs finalités qui vont au-delà des objectifs de cette page. Pour l’occasion, nous limiterons son intérêt à la fonction d’installation des modules Node.js. L’installation peut se faire à deux niveaux : | ||
# Installation en | # Installation en '''local''' dans la position actuelle en ligne de commande | ||
# Installation | # Installation '''globale''' dans le système | ||
En | |||
npm install -g | En règle général, il est de bonne pratique d'installer les modules en local, sauf s'il s'agit d'outils de soutient au développement en général, pas seulement dans le cadre d'une application. Voici par exemple le code pour installer le module [https://www.npmjs.com/package/live-server live-server] qui permet de lancer un serveur web en local : | ||
Pour une installation locale il faut tout simplement enlever le paramètre <code>-g</code>. Dans ce cas les fichiers seront installés dans un répertoire node_modules dans la position actuelle de la ligne de commande. | |||
npm install -g live-server | |||
Pour une installation locale, il faut tout simplement enlever le paramètre <code>-g</code>. Dans ce cas les fichiers seront installés dans un répertoire <code>node_modules</code> dans la position actuelle de la ligne de commande. | |||
Pour une introduction au fonctionnement de npm voir : | |||
* {{ Goblock | [https://docs.npmjs.com/getting-started/what-is-npm What is npm?]}} sur le site officiel. | |||
==Comprendre Node.js== | ==Comprendre Node.js== | ||
Même si Node.js utilise JavaScript, il ne suffit pas de connaître JavaScript pour comprendre et savoir utiliser Node.js « out of the box ». La connaissance des bases de JavaScript ( | Même si Node.js utilise JavaScript, il ne suffit pas de connaître JavaScript pour comprendre et savoir utiliser Node.js « out of the box ». La connaissance des bases de JavaScript (notamment les fondamentaux du langage) est une condition indispensable, mais pas suffisante pour écrire du code avec Node. En d’autres termes, si sur une échelle de 1 à 10 vous avez une connaissance de JavaScript de 10, cela ne signifie pas que vous aurez automatiquement une connaissance de 10 de Node.js. Par contre, si vous avez une connaissance de 4 en JavaScript, il est pratiquement impossible que vous ayez une connaissance supérieure à 4 en Node.js. | ||
===Comparaison avec JavaScript côté-client=== | ===Comparaison avec JavaScript côté-client=== | ||
Un parallèle avec JavaScript dans les navigateurs peut aider à comprendre le concept de base de Node. | Un parallèle avec JavaScript dans les navigateurs peut aider à comprendre le concept de base de Node. | ||
====L’objet window vs. les modules Node.js==== | ====L’objet window vs. les modules Node.js==== | ||
On peut en effet affirmer que si JavaScript côté client permet un certain contrôle sur le navigateur web des utilisateurs grâce à l’objet global window, Node.js permet un grand contrôle sur l’ensemble de l’environnement hôte, c’est-à-dire le dispositif sur lequel « tourne » Node.js. Si, avec JavaScript côté-client, le développeur peut utiliser des propriétés et des méthodes de l’objet window pour déterminer certains comportements de l’application, avec Node.js il pourra utiliser les propriétés et les méthodes d’autres types d’objets, c’est-à-dire des modules, qui permettent d’interagir avec le système et ses composantes. | On peut en effet affirmer que si JavaScript côté client permet un certain contrôle sur le navigateur web des utilisateurs grâce à l’objet global window, Node.js permet un grand contrôle sur l’ensemble de l’environnement hôte, c’est-à-dire le dispositif sur lequel « tourne » Node.js. Si, avec JavaScript côté-client, le développeur peut utiliser des propriétés et des méthodes de l’objet window pour déterminer certains comportements de l’application, avec Node.js il pourra utiliser les propriétés et les méthodes d’autres types d’objets, c’est-à-dire des modules, qui permettent d’interagir avec le système et ses composantes. | ||
Par exemple le module <code>fs</code> ( | Par exemple le module <code>fs</code> (File System) est un module qui permet au développeur d’interagir avec le gestionnaire des fichiers du système d’exploitation et par conséquent de pouvoir utiliser des méthodes pour créer, renommer, effacer, copier, etc. des fichiers. | ||
====Les événements de l’utilisateur vs. les événements du système==== | ====Les événements de l’utilisateur vs. les événements du système==== | ||
Une similitude s’applique également à l’approche orientée | Une similitude s’applique également à l’approche orientée événements de JavaScript côté-client, qui est présente dans Node.js. Dans une approche évènementielle, du code est exécuté lorsqu’un certain événement a lieu. La différence entre côté-client et Node.js consiste dans le fait que pour JavaScript côté-client les événements se réfèrent principalement à des actions de l’utilisateur, confinées à chaque séance individuelle de cet utilisateur sur la page. Au contraire, avec Node.js, les événements acquièrent une portée globale et se réfèrent aux événements liés à l’ensemble de l’application Node.js et son interaction avec le système hôte et ses composantes. | ||
Node.js utilise un gestionnaire d’événements qu’on appelle | Node.js utilise un gestionnaire d’événements qu’on appelle « event loop » et qui est représenté dans le diagramme suivant : | ||
[[Fichier:Node.js event loop.png|none|thumb|600x600px|Node.js event loop, adapté depuis Wilson (2013).]] | [[Fichier:Node.js event loop.png|none|thumb|600x600px|Node.js event loop, adapté depuis Wilson (2013).]] | ||
Ligne 134 : | Ligne 167 : | ||
# Le principe du non-blocking | # Le principe du non-blocking | ||
# Les fonctions de callback | # Les fonctions de callback | ||
===Non-blocking I/O et callback=== | ===Non-blocking I/O et callback=== | ||
Pour bien comprendre ce passage il faut avoir à l’esprit que tout mécanisme d’I/O requière une certaine puissance de | Pour bien comprendre ce passage, il faut avoir à l’esprit que tout mécanisme d’I/O requière une certaine puissance de calcul, c’est-à-dire du temps pour exécuter des opérations, soit symboliques (e.g., calculer le résultat d’un algorithme), soit physiques (e.g. écrire du texte dans un fichier et le sauvegarder). Dans la plupart des langages de programmation, ces opérations d’Input/Output sont exécutées lorsque l’interprète les « rencontre » dans le code source, et avant de poursuivre dans la lecture du code, l’interprète attend que l’opération se termine. En d’autres termes, l’opération bloque la poursuite de l’exécution du code. Ce type de mécanisme, qui s’applique notamment à JavaScript côté-client, a l’avantage que les opérations se font en séquence, et donc ce qui est disponible à la ligne de code 1 sera aussi disponible à la ligne de code 2. Voici un exemple côté-client qui montre ce principe: | ||
//Code JavaScript côté-client !! | //Code JavaScript côté-client !! | ||
var monNom = prompt(‘What is your name ?’); | var monNom = prompt(‘What is your name ?’); | ||
console.log(monNom); | console.log(monNom); | ||
Dans JavaScript côté-client, la méthode <code>prompt</code> de l’objet global window bloque l’exécution du script jusqu’à ce que l’utilisateur | Dans JavaScript côté-client, la méthode <code>prompt</code> de l’objet global window bloque l’exécution du script jusqu’à ce que l’utilisateur fournisse une réponse dans la boîte qui s’affiche dans le navigateur, ce qui met donc les autres lignes du code en attente. Pour éviter ce type de blocage, Node.js exploite à fond les événements asynchrones en associant ce qu’on appelle une fonction de callback à des opérations qui tendent à prendre du temps et donc à bloquer potentiellement la lecture du code. Une fonction de callback est une fonction qui est appelée lorsqu’une opération est terminée et qui reçoit automatiquement le résultat de la première opération en tant qu’argument. Voici un exemple fictif de fonction de callback qui affiche le contenu d’un fichier une fois la lecture terminée (pour un exemple réel de ce mécanisme voir le module <code>fs</code> plus bas dans la page) : | ||
Pour éviter ce type de | |||
//Code illustratif, pas exemple réel !! | //Code illustratif, pas exemple réel !! | ||
lireLeFichier(‘fichier.txt’, function (contenu) { | lireLeFichier(‘fichier.txt’, function (contenu) { | ||
//faire quelque chose avec le contenu | //faire quelque chose avec le contenu | ||
console.log(contenu); | |||
} | |||
L'anatomie d'une fonction qui prévoit un callback exploite le fait que les fonctions en JavaScript sont des "first class citizens" et peuvent donc être utilisées comme n'importe quel autre objet de JavaScript. Il s'ensuit qu'on peut passer des fonctions en tant qu'arguments d'une autre fonction : | |||
//Code illustratif de la déclaration d'un fonction avec callback | |||
function myFunction(myCallback) { | |||
//Exécuter une opération qui prend du temps, par exemple une opération itérative ou une opération de système | |||
var i = 0; | |||
while (i < 100000) { | |||
i++; | |||
} | |||
//Une fois cette opération terminée, appeler la fonction de callback avec un argument qui résulte de l'opération | |||
myCallback(i); | |||
} | } | ||
À ce point, on peut placer le nom de n'importe quel type de fonction qui prévoit un argument à l'intérieur de la fonction myFunction() pour faire quelque chose avec son résultat : | |||
//Code illustratif de l'utilisation d'une fonction de callback anonyme | |||
myFunction(function (i) { | |||
console.log("J'ai compté jusqu'à " + i); | |||
}); | |||
//--> J'ai compté jusqu'à 100000 | |||
On peut obtenir le même résultat avec une fonction déclarée plutôt qu'anonyme : | |||
//Déclarer la fonction | |||
function printCount (i) { | |||
console.log("J'ai compté jusqu'à " + i); | |||
} | |||
//L'utiliser en tant que callback | |||
myFunction(printCount); | |||
//--> J'ai compté jusqu'à 100000 | |||
===Qu’est-ce qu’un module Node.js=== | ===Qu’est-ce qu’un module Node.js=== | ||
Les « building blocks » de Node.js sont les modules, c’est-à-dire des extensions – sous forme | Les « building blocks » de Node.js sont les modules, c’est-à-dire des extensions – sous forme d’objets – qui permettent d’accéder à des propriétés et des méthodes en lien avec le système hôte (c.-à-d. l’environnement) et à d’autres éléments qui peuvent être utiles dans le cadre d’une application (exemple : base de données, client e-mail, etc.). Contrairement à l’objet global window dans JavaScript côté-client, les différents modules de Node.js ne sont pas toujours disponibles dans l’application : ils seraient trop nombreux et trop lourds à charger dans chaque application. De ce fait, le programmateur doit identifier à l’avance les modules dont il aura besoin pour son application et les importer dans son application. | ||
====Anatomie d’un module==== | ====Anatomie d’un module==== | ||
Un module est l’équivalent d’un objet personnalisé en JavaScript, mais avec la particularité que le programmateur peut décider de rendre seulement certaines méthodes et propriétés de cet objet disponibles dans d’autres scripts. Pour ce faire, on utilise l’objet <code>exports</code> qui détermine les méthodes et propriétés « publiques » du module. Voici un exemple d’un module inclus dans le fichier <code>stic.js</code> : | Un module est l’équivalent d’un objet personnalisé en JavaScript, mais avec la particularité que le programmateur peut décider de rendre seulement certaines méthodes et propriétés de cet objet disponibles dans d’autres scripts. Pour ce faire, on utilise l’objet <code>exports</code> qui détermine les méthodes et propriétés « publiques » du module. Voici un exemple d’un module inclus dans le fichier <code>stic.js</code> : | ||
Ligne 163 : | Ligne 229 : | ||
} | } | ||
</source> | </source> | ||
Ce script n’est pas censé faire quelque chose. Au contraire, son utilité | Ce script n’est pas censé faire quelque chose. Au contraire, son utilité est d’être incluse dans un autre script qui puisse se servir des méthodes publiques <code>addSubject()</code> et <code>about()</code>. Pour ce faire, il faut inclure le module dans le fichier du script grâce à la fonction <code>require()</code>. Voici un exemple de script contenu dans un fichier script.js qui se trouve dans la même position du fichier stic.js : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
//Fichier script.js qui représente le script à exécuter | //Fichier script.js qui représente le script à exécuter | ||
Ligne 180 : | Ligne 246 : | ||
# Le '''nom d’un module natif''' de Node.js (voir plus bas dans la page) -> require(‘fs’) ; | # Le '''nom d’un module natif''' de Node.js (voir plus bas dans la page) -> require(‘fs’) ; | ||
# Le '''nom d’un module installé avec npm''' (de manière global ou dans le dossier node_modules) -> require(‘mysql’) ; | # Le '''nom d’un module installé avec npm''' (de manière global ou dans le dossier node_modules) -> require(‘mysql’) ; | ||
Normalement, on associe la fonction <code>require()</code> à una variable ainsi que les propriétés et les méthodes exportées peuvent être utilisées grâce à la notation par point : | Normalement, on associe la fonction <code>require()</code> à una variable ainsi que les propriétés et les méthodes exportées qui peuvent être utilisées grâce à la notation par point : | ||
var myModule = require(‘./myModule.js’); | var myModule = require(‘./myModule.js’); | ||
myModule.myProperty; | myModule.myProperty; | ||
Ligne 232 : | Ligne 298 : | ||
Dans cette section nous présentons un aperçu d’une sélection de modules disponibles « out of the box » avec l’installation de Node.js sur un système. Pour une liste plus exhaustive se référer à la [https://nodejs.org/api/ documentation de l’API sur le site officiel]. | Dans cette section nous présentons un aperçu d’une sélection de modules disponibles « out of the box » avec l’installation de Node.js sur un système. Pour une liste plus exhaustive se référer à la [https://nodejs.org/api/ documentation de l’API sur le site officiel]. | ||
===fs : le FileSystem=== | ===fs : le FileSystem=== | ||
Le module <code>fs</code> (voir [https://nodejs.org/api/fs.html documentation API]) permet d’exécuter les opérations les plus communes sur des fichiers et des dossiers | Le module <code>fs</code> (voir [https://nodejs.org/api/fs.html documentation API]) permet d’exécuter les opérations les plus communes sur des fichiers et des dossiers tels que créer, modifier, effacer, changer les permissions, ou encore obtenir des informations sur la taille, sur la dernière modification, etc. Pour chaque opération il existe normalement deux méthodes, une méthode synchrone (blocking) et une méthode asynchrone (non-blocking) avec fonction de callback (voir plus haut dans la page). | ||
'''Veuillez faire attention, surtout avec les fonctions qui remplacent le contenu ou effacent des fichiers, car ces opérations sont irréversibles !''' Node.js ne met pas les fichiers effacés dans la corbeille par exemple. | '''Veuillez faire attention, surtout avec les fonctions qui remplacent le contenu ou effacent des fichiers, car ces opérations sont irréversibles !''' Node.js ne met pas les fichiers effacés dans la corbeille par exemple. | ||
Ligne 241 : | Ligne 307 : | ||
Les deux fonctions sont similaires à l’exception de la présence de la fonction de callback pour la lecture asynchrone. Les arguments communs des deux fonctions sont : | Les deux fonctions sont similaires à l’exception de la présence de la fonction de callback pour la lecture asynchrone. Les arguments communs des deux fonctions sont : | ||
# Le fichier à lire, avec sa position absolue ou relative à la position du script qui invoque la méthode | # Le fichier à lire, avec sa position absolue ou relative à la position du script qui invoque la méthode | ||
# Des options dont la plus utile concerne l’encodage du résultat de la fonction qui permet d’obtenir le contenu du fichier en tant que String (suite de caractères) | # Des options dont la plus utile concerne l’encodage du résultat de la fonction qui permet d’obtenir le contenu du fichier en tant que String (suite de caractères). Si l'encodage n'est pas spécifié, le résultat sera disponible en terme de Buffer (c.-à-d. code binaire), donc plus complexe à traiter. | ||
La fonction asynchrone nécessite ensuite | La fonction asynchrone nécessite ensuite une fonction de callback qui reçoit les deux arguments suivants : | ||
# Error : si la lecture n’est pas | # Error : si la lecture n’est pas possible, le système propose le type d’erreur rencontré | ||
# Data : le contenu du fichier | # Data : le contenu du fichier | ||
Voici un exemple de lecture '''asynchrone''' d’un fichier <code>file.txt</code> qui contient tout simplement la phrase <code> Texte dans le fichier!</code> : | Voici un exemple de lecture '''asynchrone''' d’un fichier <code>file.txt</code> qui contient tout simplement la phrase <code> Texte dans le fichier!</code> : | ||
Ligne 269 : | Ligne 335 : | ||
Texte dans la console! | Texte dans la console! | ||
Texte dans le fichier! | Texte dans le fichier! | ||
On peut noter que c’est le message « Texte dans la console ! » s’affiche avant le contenu du fichier car on a utilisé une fonction non-blocking, par conséquent l’interprète a continué | On peut noter que c’est le message « Texte dans la console ! » qui s’affiche avant le contenu du fichier car on a utilisé une fonction non-blocking, par conséquent l’interprète a continué de lire les instructions pendant qu’il lisait le contenu du fichier file.txt. | ||
Voici le même exemple mais en utilisant la fonction '''synchrone''' : | Voici le même exemple mais en utilisant la fonction '''synchrone''' : | ||
Ligne 291 : | Ligne 357 : | ||
On peut noter que, contrairement à l’exemple asynchrone précédent, dans ce cas l’ordre des messages respecte l’ordre du code dans le fichier, car nous avons utilisé une fonction synchrone qui a bloqué l’exécution du code pendant la lecture du contenu du fichier file.txt. | On peut noter que, contrairement à l’exemple asynchrone précédent, dans ce cas l’ordre des messages respecte l’ordre du code dans le fichier, car nous avons utilisé une fonction synchrone qui a bloqué l’exécution du code pendant la lecture du contenu du fichier file.txt. | ||
Une fois | Une fois le contenu du fichier obtenu, on peut ensuite utiliser du "simple" JavaScript par exemple pour créer des array et utiliser les données dans des algorithmes. Voici un exemple qui extrait les notes d'un fichier de texte appelé <code>notes.txt</code> dont le contenu est illustré par la suite : | ||
Student 1, 4.5, 4, 5.5, 3.5, 4.75 | Student 1, 4.5, 4, 5.5, 3.5, 4.75 | ||
Ligne 298 : | Ligne 364 : | ||
Student 4, 2.75, 4.25, 3.25, 4, 4.5 | Student 4, 2.75, 4.25, 3.25, 4, 4.5 | ||
Nous pouvons exploiter la fonction JavaScript <code>split()</code> pour séparer les étudiants par ligne (qui dans un fichier de type .txt est | Nous pouvons exploiter la fonction JavaScript <code>split()</code> pour séparer les étudiants par ligne (qui dans un fichier de type .txt est représenté par \n) et l'utilisation des virgules pour récupérer la moyenne de chaque étudiant. Voici le code : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 323 : | Ligne 389 : | ||
total += parseFloat(notes[j]); | total += parseFloat(notes[j]); | ||
} | } | ||
//Diviser le total par l'array des notes (-1 parce que le premier élément est le nom de l'étudiant) | //Diviser le total par le nombre d'élément de l'array des notes (-1 parce que le premier élément est le nom de l'étudiant) | ||
var moyenne = total/ (notes.length - 1); | var moyenne = total / (notes.length - 1); | ||
console.log("L'étudiant " + student + " a une moyenne de " + moyenne); | console.log("L'étudiant " + student + " a une moyenne de " + moyenne); | ||
} | } | ||
Ligne 338 : | Ligne 404 : | ||
====Écrire le contenu d’un fichier==== | ====Écrire le contenu d’un fichier==== | ||
Pour écrire le contenu d’un fichier on peut utiliser la fonction <code>writeFile()</code> ou sa version synchrone <code>writeFileSync()</code>. Le comportement de ces fonctions est similaire aux fonctions <code>readFile()</code> et <code>readFileSync()</code> illustrées au point précédent, mais avec l’opération d’écriture. Les deux fonctions écrivent le contenu dans un fichier passé en argument, si le fichier existe déjà, le contenu de ce fichier sera remplacé. Si le fichier n’existe pas encore, il sera créé automatiquement. | Pour écrire le contenu d’un fichier on peut utiliser la fonction <code>writeFile()</code> ou sa version synchrone <code>writeFileSync()</code>. Le comportement de ces fonctions est similaire aux fonctions <code>readFile()</code> et <code>readFileSync()</code> illustrées au point précédent, mais avec l’opération d’écriture. Les deux fonctions écrivent le contenu dans un fichier passé en argument, et si le fichier existe déjà, le contenu de ce fichier sera remplacé. Si le fichier n’existe pas encore, il sera créé automatiquement. | ||
La fonction <code>writeFile()</code> accepte les arguments suivants : | La fonction <code>writeFile()</code> accepte les arguments suivants : | ||
# Le nom du fichier (avec éventuellement sa position absolue ou relative au script) dans lequel placer le contenu | # Le nom du fichier (avec éventuellement sa position absolue ou relative au script) dans lequel placer le contenu | ||
Ligne 345 : | Ligne 411 : | ||
# La fonction de callback | # La fonction de callback | ||
fs.writeFile(fichier, contenu, [options], callback) ; | fs.writeFile(fichier, contenu, [options], callback) ; | ||
Voici un exemple – tiré de la documentation officielle de Node.js (veuillez noter qu'il faut importer le module fs pour que cet exemple puisse marcher, | Voici un exemple – tiré de la documentation officielle de Node.js (veuillez noter qu'il faut importer le module fs pour que cet exemple puisse marcher, c.-à-d. <code>var fs = require('fs')</code>) – qui écrit une simple phrase dans un fichier <code>message.txt</code> de manière asynchrone : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 354 : | Ligne 420 : | ||
</source> | </source> | ||
Si vous voulez ajouter le contenu à un fichier plutôt que remplacer | Si vous voulez ajouter le contenu à un fichier plutôt que de le remplacer, alors vous pouvez utiliser la fonction <code>appendFile()</code> (si le fichier n'existe pas, il sera créé automatiquement). Voici un exemple tiré encore une fois de la documentation officielle de Node : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 364 : | Ligne 430 : | ||
====Lister les fichiers présents dans un dossier==== | ====Lister les fichiers présents dans un dossier==== | ||
Le module <code>fs</code> permet également d'agir sur les dossiers. Par exemple la fonction <code>fs.readdir()</code> (disponible également en modalité synchrone) permet de lister les fichiers contenus dans un dossier. Voici d'abord l'arborescence pour comprendre les références | Le module <code>fs</code> permet également d'agir sur les dossiers. Par exemple la fonction <code>fs.readdir()</code> (disponible également en modalité synchrone) permet de lister les fichiers contenus dans un dossier. Voici d'abord l'arborescence pour comprendre les références des chemins de fichiers : | ||
directory | directory | ||
Ligne 397 : | Ligne 463 : | ||
===path : le chemin des fichiers === | ===path : le chemin des fichiers === | ||
Un autre module utilisé | Un autre module souvent utilisé avec le module du File System est le module <code>path</code> qui permet d'effectuer des opérations sur les chemins des fichiers. Veuillez noter que cette opération ne concerne pas les fichiers physiques, comme dans le cas de <code>fs</code>, mais simplement la référence à leur position dans le système. | ||
Pour utiliser le module path, il faut tout simplement l'importer : | Pour utiliser le module path, il faut tout simplement l'importer : | ||
Ligne 449 : | Ligne 515 : | ||
===http : le module pour le web=== | ===http : le module pour le web=== | ||
Node.js est pensé principalement pour les applications web et par conséquent le protocol http possède une grande importance. Cette importance | Node.js est pensé principalement pour les applications web et par conséquent le protocol http possède une grande importance. Cette importance se traduit par le module <code>http</code> qui permet d'exécuter plusieurs types d'opérations de type '''requête/réponse''' (voir également [[Express.js]] pour plus de détails). | ||
Pour utiliser le module <code>http</code> (qui existe également dans sa version https) il est suffisant de l'importer : | Pour utiliser le module <code>http</code> (qui existe également dans sa version https) il est suffisant de l'importer : | ||
Ligne 457 : | Ligne 523 : | ||
====Créer un simple server web==== | ====Créer un simple server web==== | ||
Contrairement à d'autres | Contrairement à d'autres interprètes (comme par exemple PHP) qui nécessitent un server web sous-jacent (e.g. Apache), Node.js permet de créer soi-même un script qui génère un server web. Les exemples suivants montrent des server web très simples, qui ont tout simplement un objectif pédagogique démonstratif au niveau du mécanisme requête/réponse. Pour créer des server web à utiliser "sérieusement", il est bien de s'appuyer plutôt sur des modules plus complexes tels que [http://expressjs.com/ express]. | ||
La création d'un server web de base en Node.js se fait avec la méthode<code>createServer</code> du module <code>http</code>. Cette méthode accepte comme paramètre une fonction dont l'utilité est de gérer le mécanisme requête/réponse à travers des objects qui sont automatiquement disponibles en tant qu'arguments. | La création d'un server web de base en Node.js se fait avec la méthode<code>createServer</code> du module <code>http</code>. Cette méthode accepte comme paramètre une fonction dont l'utilité est de gérer le mécanisme requête/réponse à travers des objects qui sont automatiquement disponibles en tant qu'arguments. | ||
Ce premier exemple ne considère que la réponse, c'est-à-dire que vous obtenez toujours la même page n'importe | Ce premier exemple ne considère que la réponse, c'est-à-dire que vous obtenez toujours la même page pour n'importe quel type de requête (voir plus bas) : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
//Importer le module http | //Importer le module http | ||
Ligne 478 : | Ligne 544 : | ||
</source> | </source> | ||
Vous pouvez à ce moment ouvrir votre navigateur et pointer à l'adresse http://localhost:1337 pour voir votre simple page web. Étant donné que le | Vous pouvez, à ce moment-là, ouvrir votre navigateur et pointer à l'adresse http://localhost:1337 pour voir votre simple page web. Étant donné que le serveur créé ne gère pas les requêtes, vous pouvez pointer à n'importe quelle page de cette adresse, mais vous allez obtenir toujours la même page (exemple : http://localhost:1337/page1.html ou http://localhost:1337/page2.html). Ceci nous permet d'introduire très brièvement l'objet requête. Dans l'exemple suivant, le message de la réponse tient en compte l'url demandé par la requête : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 497 : | Ligne 563 : | ||
</source> | </source> | ||
Maintenant, vous pouvez essayer d' | Maintenant, vous pouvez essayer d'accéder à différents url sur votre server web (exemple : http://localhost:1337/page1.html ou http://localhost:1337/page2.html) et le message affiché tiendra compte de l'url. Vous pouvez à ce moment-là imaginer de combiner ce serveur web avec le module <code>fs</code> pour envoyer en tant que réponse le contenu d'un fichier du même nom que la page de l'url pour créer un serveur web statique très simple. | ||
* [http://blog.modulus.io/build-your-first-http-server-in-nodejs Tutoriel en anglais qui explique mieux la création d'un simple server web] | * [http://blog.modulus.io/build-your-first-http-server-in-nodejs Tutoriel en anglais qui explique mieux la création d'un simple server web] | ||
Ligne 503 : | Ligne 569 : | ||
====Lire le contenu d'une page à travers une requête http==== | ====Lire le contenu d'une page à travers une requête http==== | ||
Une des applications | Une des applications possibles du module http concerne la possibilité d'émuler des requêtes d'un navigateur, ce qui peut être très utile notamment dans le cadre du [[web scraping]]. Le module <code>http</code> met à disposition la méthode <code>http.request()</code> pour ce type d'activité. Il existe également une version simplifiée qui ne considère que la requête de type GET avec justement la méthode <code>http.get()</code>. Dans l'exemple suivant, nous allons faire une requête sur cette même page et obtenir son contenu html. Veuillez noter que le module http est asynchrone, et donc l'échange des données se fait "par morceaux". | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 532 : | Ligne 598 : | ||
==Modules à installer avec npm== | ==Modules à installer avec npm== | ||
À travers le gestionnaire [https://www.npmjs.com/ npm] il est | À travers le gestionnaire [https://www.npmjs.com/ npm] il est possible d'utiliser des modules qui permettent d'avoir des solutions déjà prêtes qui ont été développées (et sont maintenues) par d'autres développeurs. L'écosystème npm propose des milliers de "paquets" dont les objectifs sont très variés. Ci-dessous, nous proposons quelques paquets/modules parmi les plus connus ou qui sont en relation avec le cours [[STIC I]]. | ||
===Exemple propédeutique avec figlet=== | ===Exemple propédeutique avec figlet=== | ||
D'abord un simple exemple propédeutique tiré du [http://eloquentjavascript.net/20_node.html chapitre 20 du livre | D'abord un simple exemple propédeutique tiré du [http://eloquentjavascript.net/20_node.html chapitre 20 du livre éloquent JavaScript] qui permet une introduction à l'utilisation des modules avec le paquet <code>figlet</code>. Ce paquet permet tout simplement de transformer du texte an ASCII art. Voici un exemple avec le texte "Hello World!" | ||
_ _ _ _ _ _ _ | _ _ _ _ _ _ _ | ||
Ligne 544 : | Ligne 610 : | ||
|_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_) | |_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_) | ||
Pour utiliser le module il faut d'abord l'installer. Pour cet exemple nous allons l'installer de manière locale, donc dans le même dossier de notre script. Pour ce faire, rendez-vous dans un dossier sur votre système avec la ligne de commande et lancez cette commande : | Pour utiliser le module il faut d'abord l'installer. Pour cet exemple, nous allons l'installer de manière locale, donc dans le même dossier de notre script. Pour ce faire, rendez-vous dans un dossier sur votre système avec la ligne de commande et lancez cette commande : | ||
npm install figlet | npm install figlet | ||
Ligne 556 : | Ligne 622 : | ||
|- ... | |- ... | ||
Le dossier figlet contient les fichiers du module, c'est-à-dire tous les éléments qui permettent de transformer du texte en ASCII art. Pour créer notre script, on peut maintenant importer le module exactement comme c'est le cas pour les modules natifs : | |||
var figlet = require('figlet'); | var figlet = require('figlet'); | ||
Voici le script complet pour transformer le texte "EduTechWiki" | Voici le script complet pour transformer le texte "EduTechWiki" et l'afficher dans la console : | ||
<source lang="JavaScript"> | <source lang="JavaScript"> | ||
Ligne 566 : | Ligne 632 : | ||
figlet.text("EduTechWiki", function(error, data) { | figlet.text("EduTechWiki", function(error, data) { | ||
if (error) | if (error) { | ||
console.error(error); | console.error(error); | ||
else | } else { | ||
console.log(data); | console.log(data); | ||
} | |||
}); | }); | ||
</source> | </source> | ||
Ligne 581 : | Ligne 648 : | ||
|_____\__,_|\__,_||_|\___|\___|_| |_|\_/\_/ |_|_|\_\_| | |_____\__,_|\__,_||_|\___|\___|_| |_|\_/\_/ |_|_|\_\_| | ||
===Express=== | ===Express.js=== | ||
[[Express.js]] est l'un des modules les plus utilisés en Node.js. Ce module est, en effet, un véritable framework qui facilite le développement d'application web dynamiques, en fournissant des éléments tels que : | |||
* Des '''''routes''''' pour intercepter différents types de requêtes et fournir des réponses correspondantes | |||
* Des '''''middleware''''' qui se placent entre la requête et la réponse pour automatiser certaines opérations au niveau global (exemple : contrôler que l'utilisateur soit connecté) | |||
* Des '''''templates engines''''' qui permettent de générer du html de manière automatisée | |||
* Un '''générateur''' qui crée automatiquement une structure de dossiers et de fichiers qui facilitent l'organisation (c'est-à-dire la structure) d'une application web | |||
Express.js peut être installé normalement en tant que module avec la commande npm suivante : | |||
npm install express | |||
* Voir la page sur [[Express.js]] pour plus d'information | |||
* Visitez le [http://expressjs.com/ site officiel du framework] | |||
* Voir [http://nodeframework.com/ une liste d'alternatives] | |||
===Electron=== | ===Electron=== | ||
[[Electron]] est un module très spécial car il permet de créer des applications desktop cross-plateforme (Windows, Mac et Linux) en utilisant des technologies web. Il s'agit d'un projet open-source géré par l'équipe de [https://github.com/ GitHub]. | |||
Electron combine différentes technologies afin que le développeur puisse exploiter à la fois JavaScript côté-client et Node.js dans le même environnement. En effet, Electron combine : | |||
* '''Une version du navigateur Chrome'''. Par conséquent, l'interface graphique de l'application peut être codée en HTML + CSS + JavaScript comme une page web normale; | |||
* '''Une version de Node.js'''. Par conséquent, l'application a également accès à toutes les opérations I/O des modules natifs de Node, plus d'autres modules à installer avec npm. | |||
L'avantage de cette combinaison concerne le fait qu'on peut intégrer du JavaScript côté-client directement avec du Node.js. On peut donc, par exemple, imaginer un code similaire à celui ci : | |||
<source lang="JavaScript"> | |||
//Importer le module File System | |||
var fs = require('fs'); | |||
//Identifier un bouton dans le DOM de la page | |||
var btn = document.getElementById("myBtnHTML"); | |||
//Identifier un champ de texte dans le DOM de la page | |||
var texte = document.getElementById("myTextFieldHTML"); | |||
//Identifier un div qui affichera un feedback | |||
var feedback = document.getElementById("myFeedbackDivHTML"); | |||
//Ajouter un listener au click du bouton | |||
btn.onclick = function () { | |||
//Sauvegarder le contenu du champ de texte dans un fichier dans le File System | |||
fs.writeFile('fichier.txt', texte.value, function (error) { | |||
if(error) throw error; | |||
//Afficher une confirmation de sauvegarde dans le div feedback | |||
feedback.innerHTML = "Le fichier a été sauvegardé correctement !"; | |||
}); | |||
} | |||
</source> | |||
Veuillez noter que cet exemple ne prend pas en compte la façon d'inclure le module Electron. Cette opération est en effet un peu plus complexe par rapport au simple require(). | |||
* Voir la page sur [[Electron]] pour plus d'information | |||
* Visitez le [http://electron.atom.io/ site officiel du projet] | |||
==Bibliographie== | ==Bibliographie== | ||
* Wilson, J. R. (2013). ''Node.js the Right Way''. The Pragmatic Bookshelf. | * Wilson, J. R. (2013). ''Node.js the Right Way''. The Pragmatic Bookshelf. | ||
* Haverbeke, M. (2014). ''[http://eloquentjavascript.net/ Eloquent JavaScript]''. No Starch Press. Le livre est disponible en version papier (payante), mais également sur le web sous licence Creative Commons attribution-noncommercial license. | |||
==Liens== | ==Liens== | ||
Ligne 596 : | Ligne 710 : | ||
* [http://blog.modulus.io/absolute-beginners-guide-to-nodejs Tutoriel pour débutant sur Modulus.io (en anglais)] | * [http://blog.modulus.io/absolute-beginners-guide-to-nodejs Tutoriel pour débutant sur Modulus.io (en anglais)] | ||
* [http://eloquentjavascript.net/20_node.html Chapitre sur Node.js] dans Eloquent JavaScript | * [http://eloquentjavascript.net/20_node.html Chapitre sur Node.js] dans Eloquent JavaScript | ||
* [http://www.johnpapa.net/how-to-use-npm-global-without-sudo-on-osx/ Installation des modules en global sur Mac OS X] (Advanced) | |||
* [https://openclassrooms.com/courses/des-applications-ultra-rapides-avec-node-js OpenClassRooms - Tutoriel pour apprendre à utiliser node.js] | |||
* [http://www.tutorialspoint.com/nodejs/nodejs_environment_setup.htm Tutoriel node.js en anglais] | |||
* [http://nodebeginner.org/ Node begginner book] | |||
* [http://nodejs.developpez.com/tutoriels/javascript/node-js-livre-debutant/ Traduction française de la page Node begginer book] | |||
* [https://github.com/workshopper/learnyounode Learn you the node], une série d'exercices pour apprendre Node.js sur github | |||
* [https://www.youtube.com/watch?v=TlB_eWDSMt4 Node.js Tutorial for Beginners: Learn Node in 1 Hour] | |||
[[Catégorie: JavaScript]] | [[Catégorie: JavaScript]] |
Dernière version du 18 février 2020 à 11:38
Initiation à la pensée computationnelle avec JavaScript | |
---|---|
Module: JavaScript sur le serveur ◀▬ ▬▶ | |
◀▬▬▶ | |
⚐ à finaliser | ☸ avancé |
⚒ 2020/02/18 | |
Catégorie: JavaScript |
Introduction
Node.js (aussi abrégé "Node" par la suite) est un interprète du langage JavaScript, qui permet d’utiliser JavaScript en dehors des navigateurs web, notamment du « côté-serveur », les desktops ou les « embedded devices ». Les caractéristiques principales de Node concernent le fonctionnement basé sur les événements et l’architecture « non-blocking » des mécanismes d’input/output (I/O). Grâce à ces particularités, Node est surtout utilisé dans le développement d’applications web « scalables », c’est-à-dire qui permettent de moduler les ressources hardware nécessaires en fonction du nombre d’utilisateurs et/ou de la puissance de calcul.
Objectifs de cette page
Cette page a comme objectif pédagogique la sensibilisation de l’utilisation de JavaScript dans d’autres environnements que le navigateur web. Elle ne propose donc pas l’illustration exhaustive des caractéristiques techniques de Node.js. Les concepts et exemples illustrés sont donc limités à des environnements de test et/ou contrôlés par les développeurs et ne doivent pas être utilisés dans des situations où la fiabilité et la sécurité sont primordiales. Pour comprendre le contenu de cette page, la connaissance des pages suivantes est conseillée :
Avertissement de sécurité
Contrairement à JavaScript côté-client, dont l’exécution est contrôlée/limitée par les navigateurs web, Node.js peut avoir accès au système d’exploitation sur lequel il est installé. Ceci signifie que si vous installez Node.js sur votre ordinateur, Node.js peut potentiellement interagir avec les fichiers du système.
Il faut donc faire beaucoup plus attention avec Node.js par rapport à JavaScript côté-client, même en phase de développement/test ! Il y a un risque de corrompre ou effacer des fichiers importants, même au niveau du fonctionnement du système !
L’écosystème Node.js
Node.js est une sorte d’écosystème qui permet aux développeurs d’utiliser JavaScript dans des fonctions de I/O telles que :
- Lire/Écrire des fichiers
- Accéder et/ou manipuler des bases de données
- Créer des applications réseaux comme des serveurs web ou des streaming audio/vidéo
- Etc.
Pour obtenir cela, Node.js met à disposition des développeurs des « modules », qui sont déjà disponibles avec l’interprète ou qui peuvent être gérés grâce à npm, un gestionnaire de bibliothèques installé automatiquement avec Node.js. Ce gestionnaire permet d’ajouter facilement des « extensions » qui peuvent être téléchargées et utilisées :
- Dans des applications Node (e.g. Express.js ou Electron)
- En tant qu’outils pour effectuer des tâches liées au développement telles que des tests (e.g. Jest), gestions de bibliothèques JavaScript et/ou CSS (exemple : GruntJS), génération de squelettes pour applications (e.g. yeoman), etc.
Quelques mots sur la ligne de commande
Pour utiliser Node.js, il faut très souvent utiliser la ligne de commande. Il y a différentes possibilités pour ouvrir une ligne de commande et cela dépend notamment du système d’exploitation utilisé, mais les commandes illustrées par la suite devraient marcher dans toutes lignes de commande. Voici une liste de logiciels de ligne de commande pour les principaux systèmes d’exploitation :
- Pour Windows utiliser Windows PowerShell
- Pour Mac utiliser le Terminal
- Pour Linux utiliser l’une des lignes de commandes disponibles selon la version.
Position dans l’arborescence du système
Lorsque vous utilisez la ligne de commande de votre ordinateur, il faut être très attentif au dossier dans lequel vous vous trouvez, car c’est au niveau de ce dossier que vont s’exécuter les éventuelles actions d’Input/Output générées par Node. L'adresse du dossier dans lequel vous vous trouvez s’affiche normalement sur la gauche de votre ligne de commande, sinon elle peut être récupérée avec la commande pwd
.
Références relatives dans les dossiers
Vous pouvez faire référence aux différents niveaux de l'arborescence par rapport à la position actuelle avec les notations suivantes :
./
fait référence au dossier actuel- attention à ne pas confondre avec
/
(sans point) qui fait référence à la racine de votre système où se trouvent des fichiers importants !
- attention à ne pas confondre avec
../
fait référence à un niveau supérieur../../
fait référence à deux niveaux supérieurs- etc.
Quelques commandes de gestion de fichiers en ligne de commande
Vous pouvez également « naviguer » à travers les dossiers directement à l’intérieur de la ligne de commande, ainsi qu’obtenir des informations sur le contenu du dossier.
Avec la commande cd
vous pouvez vous déplacer dans d’autres dossiers avec des adresses relatives ou absolues :
cd Documents
se déplace dans un dossier « Documents » contenu à l’intérieur de la position actuelle- Cela équivaut à
cd ./Documents
- Cela équivaut à
cd ../
se déplace à un niveau supérieur par rapport à la position actuellecd C:/Users/votrelogin/Music
se déplace dans la position absolue du dossier Music
Évitez de travailler en ligne de commande dans des dossiers de système de votre système d’exploitation (e.g. C:/Windows/System) ou directement dans des dossiers racines comme par exemple le dossier C:/ de Windows. Il est fortement conseillé de travailler dans des sous-dossiers créés exprès pour tester des scripts Node.js.
Pour vous orienter dans les chemins de vos dossiers, vous pouvez lire le contenu d’un dossier avec la commande ls
qui affiche tous les fichiers et dossiers contenus dans la position actuelle.
De plus, vous pouvez également utiliser des commandes pour créer, renommer ou effacer des dossiers ou des fichiers directement en ligne de commande. Ces commandes ne sont pas l’objet de cette page, donc on se limitera à l’exemple de la commande mkdir
qui permet de créer un nouveau dossier :
mkdir test
Cette commande crée un dossier nommé « test » à l’intérieur de la position actuelle de votre ligne de commande.
Installation de Node.js
L’installation de Node pour, des finalités de développement et de test, est très simple, mais plus complexe – ou du moins pour le moment (novembre 2015) – pour les environnements de production, qui ne seront pas traités dans cette page.
Node.js est disponible à travers le site officiel. Le téléchargement est disponible sur la page d’accueil, qui suggère directement la version adaptée à l’ordinateur de l’utilisateur, ou dans la page « Downloads » qui permet de choisir parmi les différentes versions disponibles.
Node est disponible pour Windows, Mac et Linux, ainsi que d’autres systèmes. Pour les systèmes Windows et Mac, Node met à disposition des versions avec « installer », ce qui représente la manière la plus simple pour ajouter Node à votre ordinateur. Il faut choisir :
- La version Windows Installer, avec extension .msi, pour Windows
- La version Macintosh Installer, avec extension .pkg, pour Mac
Ensuite, il suffit de suivre les étapes du programme d’installation. Les réglages suggérés sont adaptés pour la plupart des besoins, il ne faut donc normalement pas faire de changements. Pour les installations Windows, il faut juste être attentif à la nécessité d’ajouter Node.js au PATH afin que la commande « node » soit disponible partout dans le système. Cette option est automatiquement cochée dans les réglages suggérés, il faut donc éviter de la décocher :
De plus, à partir de la version 10.x.x
, le script d'installation propose également d'installer d'autres éléments pour compiler. Il s'agit de composantes très lourdes et qui ne servent pas dans la plupart de cas. Il est donc mieux d'éviter de cocher la case, à moins que l'on sache vraiment ce que l'on fait !
La commande node
Pour contrôler que Node a bien été installé, ouvrez la ligne de commande (voir plus haut dans la page) et tapez directement le code :
node -v
La version installée de Node.js devrait s’afficher sur la ligne de commande. Voici le résultat pour la Windows PowerShell avec Node.js version 4.2.2. Faites attention avec Linux parce qu'il arrive parfois que la commande associée ne soit pas node mais bien nodejs.
Console Node (REPL)
Lorsque vous tapez tout simplement node
, par contre, vous avez accès à la console de Node.js qui est tout à fait similaire à la console utilisée dans les navigateurs web. Ce type de console est également appelé « Read-eval-print loop » (REPL) parce qu’elle permet de :
- Lire (i.e. Read) du code
- Évaluer (i.e. Eval) les expressions
- Afficher (i.e. Print) le résultat
Vous pouvez donc saisir directement des commandes JavaScript dans la ligne de commande après le chevron >
:
Pour sortir de la modalité console de Node.js tapez deux fois sur Ctrl + C
. Cette commande est utile pour sortir de toutes les opérations en ligne de commande en général. Notez également que Ctrl + C
ne permet pas de copier du texte surligné dans la ligne de commande. Utilisez le clic droit pour copier et coller du texte.
Exécuter le code dans un fichier JavaScript
La commande node
accepte également un ou plusieurs arguments, dont le premier fait référence à un fichier.js contenant du code, alors que les suivants sont des arguments qui sont passés au script :
node [fichier.js] [arg1, arg2, …]
Pour essayer vous pouvez créer un fichier script.js dans un dossier avec le simple code suivant :
//Code dans un fichier script.js console.log(‘Script Node.js’) ;
Ensuite il faut accéder à ce dossier avec la ligne de commande (voir plus haut dans la page) et saisir :
node script.js
Si on passe des arguments à la commande, ceux-ci seront accessibles à l’intérieur d’un script grâce à un array nommé process.argv
qui se compose de la manière suivante :
- process.argv[0] = node
- process.argv[1] = nom du fichier avec le script (e.g. script.js)
- process.argv[2] = premier argument passé après le nom du script
- process.argv[3] = deuxième argument passé après le nom du script
- …
Voici le code d’un fichier script.js qui écrit dans la console un message avec l’argument passé après le nom du script :
//Code dans un fichier script.js var nom = process.argv[2]; console.log("Hello " + nom);
Pour obtenir un message de hello il faut donc écrire dans la console :
node script.js votrenom
La commande npm
La commande npm
peut être utilisée pour plusieurs finalités qui vont au-delà des objectifs de cette page. Pour l’occasion, nous limiterons son intérêt à la fonction d’installation des modules Node.js. L’installation peut se faire à deux niveaux :
- Installation en local dans la position actuelle en ligne de commande
- Installation globale dans le système
En règle général, il est de bonne pratique d'installer les modules en local, sauf s'il s'agit d'outils de soutient au développement en général, pas seulement dans le cadre d'une application. Voici par exemple le code pour installer le module live-server qui permet de lancer un serveur web en local :
npm install -g live-server
Pour une installation locale, il faut tout simplement enlever le paramètre -g
. Dans ce cas les fichiers seront installés dans un répertoire node_modules
dans la position actuelle de la ligne de commande.
Pour une introduction au fonctionnement de npm voir :
- sur le site officiel.
Comprendre Node.js
Même si Node.js utilise JavaScript, il ne suffit pas de connaître JavaScript pour comprendre et savoir utiliser Node.js « out of the box ». La connaissance des bases de JavaScript (notamment les fondamentaux du langage) est une condition indispensable, mais pas suffisante pour écrire du code avec Node. En d’autres termes, si sur une échelle de 1 à 10 vous avez une connaissance de JavaScript de 10, cela ne signifie pas que vous aurez automatiquement une connaissance de 10 de Node.js. Par contre, si vous avez une connaissance de 4 en JavaScript, il est pratiquement impossible que vous ayez une connaissance supérieure à 4 en Node.js.
Comparaison avec JavaScript côté-client
Un parallèle avec JavaScript dans les navigateurs peut aider à comprendre le concept de base de Node.
L’objet window vs. les modules Node.js
On peut en effet affirmer que si JavaScript côté client permet un certain contrôle sur le navigateur web des utilisateurs grâce à l’objet global window, Node.js permet un grand contrôle sur l’ensemble de l’environnement hôte, c’est-à-dire le dispositif sur lequel « tourne » Node.js. Si, avec JavaScript côté-client, le développeur peut utiliser des propriétés et des méthodes de l’objet window pour déterminer certains comportements de l’application, avec Node.js il pourra utiliser les propriétés et les méthodes d’autres types d’objets, c’est-à-dire des modules, qui permettent d’interagir avec le système et ses composantes.
Par exemple le module fs
(File System) est un module qui permet au développeur d’interagir avec le gestionnaire des fichiers du système d’exploitation et par conséquent de pouvoir utiliser des méthodes pour créer, renommer, effacer, copier, etc. des fichiers.
Les événements de l’utilisateur vs. les événements du système
Une similitude s’applique également à l’approche orientée événements de JavaScript côté-client, qui est présente dans Node.js. Dans une approche évènementielle, du code est exécuté lorsqu’un certain événement a lieu. La différence entre côté-client et Node.js consiste dans le fait que pour JavaScript côté-client les événements se réfèrent principalement à des actions de l’utilisateur, confinées à chaque séance individuelle de cet utilisateur sur la page. Au contraire, avec Node.js, les événements acquièrent une portée globale et se réfèrent aux événements liés à l’ensemble de l’application Node.js et son interaction avec le système hôte et ses composantes. Node.js utilise un gestionnaire d’événements qu’on appelle « event loop » et qui est représenté dans le diagramme suivant :
Un exemple peut contribuer à éclaircir ce passage : lorsque le développeur demande à Node.js de lire le contenu d’un fichier, il obtiendra un événement qui détermine quand la lecture a été menée à bien. Ce simple exemple permet également d’introduire des aspects très importants de Node.js :
- Le principe du non-blocking
- Les fonctions de callback
Non-blocking I/O et callback
Pour bien comprendre ce passage, il faut avoir à l’esprit que tout mécanisme d’I/O requière une certaine puissance de calcul, c’est-à-dire du temps pour exécuter des opérations, soit symboliques (e.g., calculer le résultat d’un algorithme), soit physiques (e.g. écrire du texte dans un fichier et le sauvegarder). Dans la plupart des langages de programmation, ces opérations d’Input/Output sont exécutées lorsque l’interprète les « rencontre » dans le code source, et avant de poursuivre dans la lecture du code, l’interprète attend que l’opération se termine. En d’autres termes, l’opération bloque la poursuite de l’exécution du code. Ce type de mécanisme, qui s’applique notamment à JavaScript côté-client, a l’avantage que les opérations se font en séquence, et donc ce qui est disponible à la ligne de code 1 sera aussi disponible à la ligne de code 2. Voici un exemple côté-client qui montre ce principe:
//Code JavaScript côté-client !! var monNom = prompt(‘What is your name ?’); console.log(monNom);
Dans JavaScript côté-client, la méthode prompt
de l’objet global window bloque l’exécution du script jusqu’à ce que l’utilisateur fournisse une réponse dans la boîte qui s’affiche dans le navigateur, ce qui met donc les autres lignes du code en attente. Pour éviter ce type de blocage, Node.js exploite à fond les événements asynchrones en associant ce qu’on appelle une fonction de callback à des opérations qui tendent à prendre du temps et donc à bloquer potentiellement la lecture du code. Une fonction de callback est une fonction qui est appelée lorsqu’une opération est terminée et qui reçoit automatiquement le résultat de la première opération en tant qu’argument. Voici un exemple fictif de fonction de callback qui affiche le contenu d’un fichier une fois la lecture terminée (pour un exemple réel de ce mécanisme voir le module fs
plus bas dans la page) :
//Code illustratif, pas exemple réel !! lireLeFichier(‘fichier.txt’, function (contenu) { //faire quelque chose avec le contenu console.log(contenu); }
L'anatomie d'une fonction qui prévoit un callback exploite le fait que les fonctions en JavaScript sont des "first class citizens" et peuvent donc être utilisées comme n'importe quel autre objet de JavaScript. Il s'ensuit qu'on peut passer des fonctions en tant qu'arguments d'une autre fonction :
//Code illustratif de la déclaration d'un fonction avec callback function myFunction(myCallback) { //Exécuter une opération qui prend du temps, par exemple une opération itérative ou une opération de système var i = 0; while (i < 100000) { i++; } //Une fois cette opération terminée, appeler la fonction de callback avec un argument qui résulte de l'opération myCallback(i); }
À ce point, on peut placer le nom de n'importe quel type de fonction qui prévoit un argument à l'intérieur de la fonction myFunction() pour faire quelque chose avec son résultat :
//Code illustratif de l'utilisation d'une fonction de callback anonyme myFunction(function (i) { console.log("J'ai compté jusqu'à " + i); }); //--> J'ai compté jusqu'à 100000
On peut obtenir le même résultat avec une fonction déclarée plutôt qu'anonyme :
//Déclarer la fonction function printCount (i) { console.log("J'ai compté jusqu'à " + i); } //L'utiliser en tant que callback myFunction(printCount); //--> J'ai compté jusqu'à 100000
Qu’est-ce qu’un module Node.js
Les « building blocks » de Node.js sont les modules, c’est-à-dire des extensions – sous forme d’objets – qui permettent d’accéder à des propriétés et des méthodes en lien avec le système hôte (c.-à-d. l’environnement) et à d’autres éléments qui peuvent être utiles dans le cadre d’une application (exemple : base de données, client e-mail, etc.). Contrairement à l’objet global window dans JavaScript côté-client, les différents modules de Node.js ne sont pas toujours disponibles dans l’application : ils seraient trop nombreux et trop lourds à charger dans chaque application. De ce fait, le programmateur doit identifier à l’avance les modules dont il aura besoin pour son application et les importer dans son application.
Anatomie d’un module
Un module est l’équivalent d’un objet personnalisé en JavaScript, mais avec la particularité que le programmateur peut décider de rendre seulement certaines méthodes et propriétés de cet objet disponibles dans d’autres scripts. Pour ce faire, on utilise l’objet exports
qui détermine les méthodes et propriétés « publiques » du module. Voici un exemple d’un module inclus dans le fichier stic.js
:
//Fichier stic.js qui représente un module
//Variables qui ne sont pas disponibles avec le module
var name = "STIC I";
var subjects = ['HTML5', 'Programmation', 'JavaScript', 'Interactivité'];
//Méthode addSubject disponible avec le module
exports.addSubject = function (subject) {
subjects.push(subject);
}
//Méthode about disponible avec le module
exports.about = function () {
return name + " est un cours du Master MALTT qui porte sur " + subjects.join(", ");
}
Ce script n’est pas censé faire quelque chose. Au contraire, son utilité est d’être incluse dans un autre script qui puisse se servir des méthodes publiques addSubject()
et about()
. Pour ce faire, il faut inclure le module dans le fichier du script grâce à la fonction require()
. Voici un exemple de script contenu dans un fichier script.js qui se trouve dans la même position du fichier stic.js :
//Fichier script.js qui représente le script à exécuter
var stic = require('./stic.js');
console.log(stic.about());
stic.addSubject('Node.js');
console.log(stic.about());
Le résultat de node script.js
à la console est le suivant :
STIC I est un cours du Master MALTT qui porte sur HTML5, Programmation, JavaScript, Interactivité STIC I est un cours du Master MALTT qui porte sur HTML5, Programmation, JavaScript, Interactivité, Node.js
La fonction require
On peut utiliser les modules en les important grâce à la fonction require()
. Cette fonction accepte un argument qui peut être :
- Le path à un fichier JavaScript, avec ou sans .js final -> require(‘lib/mesmodules/stic-1’) ;
- Le nom d’un module natif de Node.js (voir plus bas dans la page) -> require(‘fs’) ;
- Le nom d’un module installé avec npm (de manière global ou dans le dossier node_modules) -> require(‘mysql’) ;
Normalement, on associe la fonction require()
à una variable ainsi que les propriétés et les méthodes exportées qui peuvent être utilisées grâce à la notation par point :
var myModule = require(‘./myModule.js’); myModule.myProperty; myModule.myMethod();
Tableau comparatif
Côté client | Node.js | |
---|---|---|
Langage utilisé | JavaScript | JavaScript |
Environnement | Navigateur web | Système hôte (ordinateur, server, dispositif, ...) |
Disponibilité | Automatique dans le navigateur | Installation nécessaire |
Version disponible | Dépend du navigateur de l'utilisateur | Dépend de la version installée sur le système |
Accès à... | Certaines fonctionnalités du navigateur | Opérations de système |
Accès grâce à... | Objet global window | Modules natifs, à installer ou personnalisés |
Opérations I/O | Limitées au navigateur | ~ Illimitées dans le système |
Événements | Plutôt liés aux actions de l'utilisateur | Plutôt liés aux opérations de système |
Exécution du code | Prioritairement synchrone (blocking) | Prioritairement asynchrone (non-blocking) |
Les modules natifs de Node.js
Dans cette section nous présentons un aperçu d’une sélection de modules disponibles « out of the box » avec l’installation de Node.js sur un système. Pour une liste plus exhaustive se référer à la documentation de l’API sur le site officiel.
fs : le FileSystem
Le module fs
(voir documentation API) permet d’exécuter les opérations les plus communes sur des fichiers et des dossiers tels que créer, modifier, effacer, changer les permissions, ou encore obtenir des informations sur la taille, sur la dernière modification, etc. Pour chaque opération il existe normalement deux méthodes, une méthode synchrone (blocking) et une méthode asynchrone (non-blocking) avec fonction de callback (voir plus haut dans la page).
Veuillez faire attention, surtout avec les fonctions qui remplacent le contenu ou effacent des fichiers, car ces opérations sont irréversibles ! Node.js ne met pas les fichiers effacés dans la corbeille par exemple.
Lire le contenu d’un fichier
Pour lire le contenu d’un fichier on peut utiliser les méthodes :
readFile(file, options, callback)
pour une lecture asynchronereadFileSync(file, options)
pour une lecture synchrone
Les deux fonctions sont similaires à l’exception de la présence de la fonction de callback pour la lecture asynchrone. Les arguments communs des deux fonctions sont :
- Le fichier à lire, avec sa position absolue ou relative à la position du script qui invoque la méthode
- Des options dont la plus utile concerne l’encodage du résultat de la fonction qui permet d’obtenir le contenu du fichier en tant que String (suite de caractères). Si l'encodage n'est pas spécifié, le résultat sera disponible en terme de Buffer (c.-à-d. code binaire), donc plus complexe à traiter.
La fonction asynchrone nécessite ensuite une fonction de callback qui reçoit les deux arguments suivants :
- Error : si la lecture n’est pas possible, le système propose le type d’erreur rencontré
- Data : le contenu du fichier
Voici un exemple de lecture asynchrone d’un fichier file.txt
qui contient tout simplement la phrase Texte dans le fichier!
:
//Importer le module FileSystem
fs = require('fs');
//Lire le contenu du fichier file.txt de manière asynchrone
//Afficher ensuite son contenu en tant que suite de caractères utf8
fs.readFile('file.txt', 'utf8', function (error, data) {
//Contrôler qu'il n'y ait pas d'erreur
if(error) {
console.log("Erreur dans la lecture du fichier");
return;
}
console.log(data);
})
//Afficher un message pour montrer l'ordre des opération
console.log("Texte dans la console!");
Le résultat à la console de ce script est le suivant :
Texte dans la console! Texte dans le fichier!
On peut noter que c’est le message « Texte dans la console ! » qui s’affiche avant le contenu du fichier car on a utilisé une fonction non-blocking, par conséquent l’interprète a continué de lire les instructions pendant qu’il lisait le contenu du fichier file.txt. Voici le même exemple mais en utilisant la fonction synchrone :
//Importer le module FileSystem
fs = require('fs');
//Lire le contenu du fichier file.txt de manière synchrone
//Afficher le contenu
var content = fs.readFileSync('file.txt', 'utf8');
console.log(content);
//Afficher un message pour montrer l'ordre des opérations
console.log("Texte dans la console!");
Le résultat à la console de ce script sera par contre le suivant :
Texte dans le fichier! Texte dans la console!
On peut noter que, contrairement à l’exemple asynchrone précédent, dans ce cas l’ordre des messages respecte l’ordre du code dans le fichier, car nous avons utilisé une fonction synchrone qui a bloqué l’exécution du code pendant la lecture du contenu du fichier file.txt.
Une fois le contenu du fichier obtenu, on peut ensuite utiliser du "simple" JavaScript par exemple pour créer des array et utiliser les données dans des algorithmes. Voici un exemple qui extrait les notes d'un fichier de texte appelé notes.txt
dont le contenu est illustré par la suite :
Student 1, 4.5, 4, 5.5, 3.5, 4.75 Student 2, 3.75, 4.25, 5, 6, 4.75 Student 3, 4.5, 5.75, 5.75, 5.5 Student 4, 2.75, 4.25, 3.25, 4, 4.5
Nous pouvons exploiter la fonction JavaScript split()
pour séparer les étudiants par ligne (qui dans un fichier de type .txt est représenté par \n) et l'utilisation des virgules pour récupérer la moyenne de chaque étudiant. Voici le code :
//Importer le module File System
var fs = require('fs');
//Lire le fichier avec les notes en tant que suite de caractères utf8
fs.readFile('notes.txt', 'utf8', function (error, data) {
//Afficher une erreur si le cas
if(error) throw error;
//Extraire chaque ligne qui représente un étudiant avec \n (new line)
var students = data.split("\n");
//Itération par ligne
for(var i = 0; i < students.length; i++) {
//Créer un array en utilisant les virgules
var notes = students[i].split(",");
//Récupérer l'étudiant courant à l'index [0]
var student = notes[0];
//Total pour calculer la moyenne ensuite
var total = 0;
//Itération par note obtenue à partir de l'array [1];
for (var j = 1; j < notes.length; j++) {
//Ajouter la note tranformé en chiffre avec parseFloat()
total += parseFloat(notes[j]);
}
//Diviser le total par le nombre d'élément de l'array des notes (-1 parce que le premier élément est le nom de l'étudiant)
var moyenne = total / (notes.length - 1);
console.log("L'étudiant " + student + " a une moyenne de " + moyenne);
}
})
L'output de ce script sera donc le suivant :
L'étudiant Student 1 a une moyenne de 4.45 L'étudiant Student 2 a une moyenne de 4.75 L'étudiant Student 3 a une moyenne de 5.375 L'étudiant Student 4 a une moyenne de 3.75
Écrire le contenu d’un fichier
Pour écrire le contenu d’un fichier on peut utiliser la fonction writeFile()
ou sa version synchrone writeFileSync()
. Le comportement de ces fonctions est similaire aux fonctions readFile()
et readFileSync()
illustrées au point précédent, mais avec l’opération d’écriture. Les deux fonctions écrivent le contenu dans un fichier passé en argument, et si le fichier existe déjà, le contenu de ce fichier sera remplacé. Si le fichier n’existe pas encore, il sera créé automatiquement.
La fonction writeFile()
accepte les arguments suivants :
- Le nom du fichier (avec éventuellement sa position absolue ou relative au script) dans lequel placer le contenu
- Le contenu du fichier qui peut être tout simplement une suite de caractères (string)
- Des options (facultatives) dont l’encodage qui est fixé à utf8 si pas spécifié
- La fonction de callback
fs.writeFile(fichier, contenu, [options], callback) ;
Voici un exemple – tiré de la documentation officielle de Node.js (veuillez noter qu'il faut importer le module fs pour que cet exemple puisse marcher, c.-à-d. var fs = require('fs')
) – qui écrit une simple phrase dans un fichier message.txt
de manière asynchrone :
fs.writeFile('message.txt', 'Hello Node.js', function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
Si vous voulez ajouter le contenu à un fichier plutôt que de le remplacer, alors vous pouvez utiliser la fonction appendFile()
(si le fichier n'existe pas, il sera créé automatiquement). Voici un exemple tiré encore une fois de la documentation officielle de Node :
fs.appendFile('message.txt', 'data to append', function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
Lister les fichiers présents dans un dossier
Le module fs
permet également d'agir sur les dossiers. Par exemple la fonction fs.readdir()
(disponible également en modalité synchrone) permet de lister les fichiers contenus dans un dossier. Voici d'abord l'arborescence pour comprendre les références des chemins de fichiers :
directory |- file1.txt |- file2.txt |- file3.txt script.js
Le fichier script.js à exécuter avec node se trouve donc dans la même position du dossier dont on veut lister le contenu. Voici le code pour le faire :
//Importer le module du File System
var fs = require('fs');
//Lire le contenu d'un dossier appelé "directory" dans le même chemin du script
//La fonction asynchrone returne une erreur, si présente, ou un array des fichiers
fs.readdir('./directory/', function (error, files) {
//Afficher l'erreur
if(error) throw error;
//Itération dans l'array files pour obtenir le nom du fichier
for(var i = 0; i < files.length; i++) {
console.log(files[i]);
}
});
Le output de ce script en console sera donc le suivant :
file1.txt file2.txt file3.txt
path : le chemin des fichiers
Un autre module souvent utilisé avec le module du File System est le module path
qui permet d'effectuer des opérations sur les chemins des fichiers. Veuillez noter que cette opération ne concerne pas les fichiers physiques, comme dans le cas de fs
, mais simplement la référence à leur position dans le système.
Pour utiliser le module path, il faut tout simplement l'importer :
var path = require('path');
Contrôler le type d'extension d'un fichier
Une méthode utile du module path
est la méthode path.extname()
qui détermine quel type d'extension - et donc quel type de fichier - est associé à un chemin donné. Voici une extension de l'exemple du File System qui liste les fichiers disponibles dans un dossier. Dans ce cas, le dossier "directory" contient 3 fichiers de texte et 3 images :
directory |- file1.txt |- file2.txt |- file3.txt |- img1.jpg |- img2.jpg |- img3.jpg script.js
Si nous voulons lister simplement les images, nous pouvons filtrer les fichiers en fonction de l'extension .jpg :
//Inclure le module File System
var fs = require('fs');
//Inclure le module pour le chemin des fichiers
var path = require('path');
//Importer le module du File System
var fs = require('fs');
//Lire le contenu d'un dossier appelé "directory" dans le même chemin du script
//La fonction asynchrone returne une erreur, si présente, ou un array des fichiers
fs.readdir('./directory/', function (error, files) {
//Afficher l'erreur
if(error) throw error;
//Itération dans l'array files pour obtenir le nom du fichier
for(var i = 0; i < files.length; i++) {
//Afficher seulement si c'est une image
if(path.extname(files[i]) === '.jpg') {
console.log(files[i]);
}
}
});
Le output du script sera donc le suivant :
img1.jpg img2.jpg img3.jpg
http : le module pour le web
Node.js est pensé principalement pour les applications web et par conséquent le protocol http possède une grande importance. Cette importance se traduit par le module http
qui permet d'exécuter plusieurs types d'opérations de type requête/réponse (voir également Express.js pour plus de détails).
Pour utiliser le module http
(qui existe également dans sa version https) il est suffisant de l'importer :
var http = require('http');
Créer un simple server web
Contrairement à d'autres interprètes (comme par exemple PHP) qui nécessitent un server web sous-jacent (e.g. Apache), Node.js permet de créer soi-même un script qui génère un server web. Les exemples suivants montrent des server web très simples, qui ont tout simplement un objectif pédagogique démonstratif au niveau du mécanisme requête/réponse. Pour créer des server web à utiliser "sérieusement", il est bien de s'appuyer plutôt sur des modules plus complexes tels que express.
La création d'un server web de base en Node.js se fait avec la méthodecreateServer
du module http
. Cette méthode accepte comme paramètre une fonction dont l'utilité est de gérer le mécanisme requête/réponse à travers des objects qui sont automatiquement disponibles en tant qu'arguments.
Ce premier exemple ne considère que la réponse, c'est-à-dire que vous obtenez toujours la même page pour n'importe quel type de requête (voir plus bas) :
//Importer le module http
var http = require('http');
//Créer le server et le gestionnaire requête/réponse et écouter sur la porte 1337
http.createServer(function (request, response) {
//La réponse contient seulement du texte
response.writeHead(200, {'Content-Type': 'text/plain'});
//La réponse finale consiste dans le message "Hello World"
response.end('Hello World\n');
}).listen(1337, "127.0.0.1");
//Message qui confirme que le server est en marche
console.log('Server running at http://127.0.0.1:1337/');
Vous pouvez, à ce moment-là, ouvrir votre navigateur et pointer à l'adresse http://localhost:1337 pour voir votre simple page web. Étant donné que le serveur créé ne gère pas les requêtes, vous pouvez pointer à n'importe quelle page de cette adresse, mais vous allez obtenir toujours la même page (exemple : http://localhost:1337/page1.html ou http://localhost:1337/page2.html). Ceci nous permet d'introduire très brièvement l'objet requête. Dans l'exemple suivant, le message de la réponse tient en compte l'url demandé par la requête :
//Importer le module http
var http = require('http');
//Créer le server et le gestionnaire requête/réponse et écouter sur la porte 1337
http.createServer(function (request, response) {
//La réponse contient seulement du texte
response.writeHead(200, {'Content-Type': 'text/plain'});
//Récuperer l'url de la page demandée
var page = request.url;
//La réponse finale montre l'url de la page demandée
response.end('You requested the page ' + page);
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');
Maintenant, vous pouvez essayer d'accéder à différents url sur votre server web (exemple : http://localhost:1337/page1.html ou http://localhost:1337/page2.html) et le message affiché tiendra compte de l'url. Vous pouvez à ce moment-là imaginer de combiner ce serveur web avec le module fs
pour envoyer en tant que réponse le contenu d'un fichier du même nom que la page de l'url pour créer un serveur web statique très simple.
Lire le contenu d'une page à travers une requête http
Une des applications possibles du module http concerne la possibilité d'émuler des requêtes d'un navigateur, ce qui peut être très utile notamment dans le cadre du web scraping. Le module http
met à disposition la méthode http.request()
pour ce type d'activité. Il existe également une version simplifiée qui ne considère que la requête de type GET avec justement la méthode http.get()
. Dans l'exemple suivant, nous allons faire une requête sur cette même page et obtenir son contenu html. Veuillez noter que le module http est asynchrone, et donc l'échange des données se fait "par morceaux".
//Inclure le module http
var http = require('http');
//Faire une requête à la page Node.js du EduTechWiki et obtenir une réponse (res)
http.get("http://edutechwiki.unige.ch/fr/Node.js", function(res) {
//Contrôler que la page existe (status code à 200)
if(res.statusCode === 200) {
//Déclarer une variable qui contiendra le contenu html de la page
var html = "";
//La réponse est asynchrone, donc le contenu de la page arrive par morceaux (i.e. chunks)
//Chaque fois qu'un chunk arrive, l'ajouter au contenu de la page
res.on("data", function (chunk) {
html += chunk;
});
//Lorsque la réponse est terminée, afficher le contenu de la page
res.on("end", function () {
console.log(html);
})
}
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
Modules à installer avec npm
À travers le gestionnaire npm il est possible d'utiliser des modules qui permettent d'avoir des solutions déjà prêtes qui ont été développées (et sont maintenues) par d'autres développeurs. L'écosystème npm propose des milliers de "paquets" dont les objectifs sont très variés. Ci-dessous, nous proposons quelques paquets/modules parmi les plus connus ou qui sont en relation avec le cours STIC I.
Exemple propédeutique avec figlet
D'abord un simple exemple propédeutique tiré du chapitre 20 du livre éloquent JavaScript qui permet une introduction à l'utilisation des modules avec le paquet figlet
. Ce paquet permet tout simplement de transformer du texte an ASCII art. Voici un exemple avec le texte "Hello World!"
_ _ _ _ _ _ _ | | | | ___| | | ___ __ _____ _ __| | __| | | | |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` | | | _ | __/ | | (_) | \ V V / (_) | | | | (_| |_| |_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_)
Pour utiliser le module il faut d'abord l'installer. Pour cet exemple, nous allons l'installer de manière locale, donc dans le même dossier de notre script. Pour ce faire, rendez-vous dans un dossier sur votre système avec la ligne de commande et lancez cette commande :
npm install figlet
Comme résultat, un dossier node_modules
sera créé dans la position actuelle de votre ligne de commande. Ce dossier aura cette arborescence :
node_modules |- figlet |- ... |- ... |- ...
Le dossier figlet contient les fichiers du module, c'est-à-dire tous les éléments qui permettent de transformer du texte en ASCII art. Pour créer notre script, on peut maintenant importer le module exactement comme c'est le cas pour les modules natifs :
var figlet = require('figlet');
Voici le script complet pour transformer le texte "EduTechWiki" et l'afficher dans la console :
var figlet = require('figlet');
figlet.text("EduTechWiki", function(error, data) {
if (error) {
console.error(error);
} else {
console.log(data);
}
});
Et voici le résultat :
_____ _ _____ _ __ ___ _ _ | ____|__| |_ |_ _|__ ___| |_\ \ / (_) | _(_) | _| / _` | | | || |/ _ \/ __| '_ \ \ /\ / /| | |/ / | | |__| (_| | |_| || | __/ (__| | | \ V V / | | <| | |_____\__,_|\__,_||_|\___|\___|_| |_|\_/\_/ |_|_|\_\_|
Express.js
Express.js est l'un des modules les plus utilisés en Node.js. Ce module est, en effet, un véritable framework qui facilite le développement d'application web dynamiques, en fournissant des éléments tels que :
- Des routes pour intercepter différents types de requêtes et fournir des réponses correspondantes
- Des middleware qui se placent entre la requête et la réponse pour automatiser certaines opérations au niveau global (exemple : contrôler que l'utilisateur soit connecté)
- Des templates engines qui permettent de générer du html de manière automatisée
- Un générateur qui crée automatiquement une structure de dossiers et de fichiers qui facilitent l'organisation (c'est-à-dire la structure) d'une application web
Express.js peut être installé normalement en tant que module avec la commande npm suivante :
npm install express
- Voir la page sur Express.js pour plus d'information
- Visitez le site officiel du framework
- Voir une liste d'alternatives
Electron
Electron est un module très spécial car il permet de créer des applications desktop cross-plateforme (Windows, Mac et Linux) en utilisant des technologies web. Il s'agit d'un projet open-source géré par l'équipe de GitHub.
Electron combine différentes technologies afin que le développeur puisse exploiter à la fois JavaScript côté-client et Node.js dans le même environnement. En effet, Electron combine :
- Une version du navigateur Chrome. Par conséquent, l'interface graphique de l'application peut être codée en HTML + CSS + JavaScript comme une page web normale;
- Une version de Node.js. Par conséquent, l'application a également accès à toutes les opérations I/O des modules natifs de Node, plus d'autres modules à installer avec npm.
L'avantage de cette combinaison concerne le fait qu'on peut intégrer du JavaScript côté-client directement avec du Node.js. On peut donc, par exemple, imaginer un code similaire à celui ci :
//Importer le module File System
var fs = require('fs');
//Identifier un bouton dans le DOM de la page
var btn = document.getElementById("myBtnHTML");
//Identifier un champ de texte dans le DOM de la page
var texte = document.getElementById("myTextFieldHTML");
//Identifier un div qui affichera un feedback
var feedback = document.getElementById("myFeedbackDivHTML");
//Ajouter un listener au click du bouton
btn.onclick = function () {
//Sauvegarder le contenu du champ de texte dans un fichier dans le File System
fs.writeFile('fichier.txt', texte.value, function (error) {
if(error) throw error;
//Afficher une confirmation de sauvegarde dans le div feedback
feedback.innerHTML = "Le fichier a été sauvegardé correctement !";
});
}
Veuillez noter que cet exemple ne prend pas en compte la façon d'inclure le module Electron. Cette opération est en effet un peu plus complexe par rapport au simple require().
- Voir la page sur Electron pour plus d'information
- Visitez le site officiel du projet
Bibliographie
- Wilson, J. R. (2013). Node.js the Right Way. The Pragmatic Bookshelf.
- Haverbeke, M. (2014). Eloquent JavaScript. No Starch Press. Le livre est disponible en version papier (payante), mais également sur le web sous licence Creative Commons attribution-noncommercial license.
Liens
- Site officiel
- Tutoriel pour débutant sur Modulus.io (en anglais)
- Chapitre sur Node.js dans Eloquent JavaScript
- Installation des modules en global sur Mac OS X (Advanced)
- OpenClassRooms - Tutoriel pour apprendre à utiliser node.js
- Tutoriel node.js en anglais
- Node begginner book
- Traduction française de la page Node begginer book
- Learn you the node, une série d'exercices pour apprendre Node.js sur github
- Node.js Tutorial for Beginners: Learn Node in 1 Hour