Tutoriel Node.js: Premiers pas avec Node.js

Node.js, un environnement d'exécution JavaScript multiplateforme pour les serveurs et les applications, offre de nombreux avantages. Une faible utilisation de la mémoire, de bonnes performances et un vaste écosystème de packages, qui sont actuellement au nombre d'environ 475000, ont fait de Node.js un choix populaire pour la création de serveurs Web, d'API REST, d'applications réseau en temps réel (par exemple, chat, jeux) et même applications de bureau multiplateformes.

Si vous n'avez pas encore commencé avec Node.js, il est peut-être temps. Consultez mon explicateur Node.js pour savoir comment Node.js fonctionne sa magie. Dans cet article, nous allons passer en revue l'installation de Node.js et du gestionnaire de packages NPM, la mise en service d'un simple serveur Web et l'utilisation du module de cluster Node.js pour tirer parti de plusieurs cœurs de processeur.

Nous examinerons également l'installation de modules Node.js supplémentaires et d'autres packages JavaScript à l'aide du gestionnaire de packages NPM. Et nous allons plonger dans l'utilisation d'un framework Node.js, dans ce cas Koa, pour créer des serveurs Node.js plus riches en fonctionnalités et flexibles.  

Commençons.

Comment installer Node.js et NPM

Commencez par naviguer sur //nodejs.org:

Fondation Node.js

Cliquez sur le bouton pour télécharger LTS (support à long terme), sauf si vous savez que vous avez besoin d'une nouvelle fonctionnalité dans la version actuelle. L'apparence exacte du programme d'installation téléchargé peut varier selon les systèmes d'exploitation, mais sur un Mac, cela ressemble à ceci au début:

Une fois l'installation terminée, cela ressemble à ceci:

Vous devez maintenant vous assurer que Node.js et NPM sont installés correctement. Ouvrez un shell de ligne de commande (Terminal sur Mac; Invite de commandes sur Windows) et vérifiez les versions installées des deux:

$ node —version

v6.11.3

$ npm —version

3.10.10

Si vous obtenez des erreurs indiquant que Node.js ou NPM n'a pas été trouvé, essayez de redémarrer votre application shell ou de redémarrer votre ordinateur. Si cela ne fonctionne pas, vous devrez peut-être modifier votre $ PATH (Mac et Linux) ou PATH (Windows) et redémarrer à nouveau.

Node.js et NPM correspondent aux versions prévues dans la capture d'écran du terminal ci-dessus, je suis donc prêt à avancer et à développer quelque chose avec Node.js. Commençons par quelque chose de facile à construire avec Node pur.

Vous aurez besoin d'un éditeur de code ou d'un IDE, de préférence un éditeur prenant en charge JavaScript et Node.js tels que Sublime Text, Visual Studio Code, Brackets, Atom ou WebStorm.

Exemple Node.js: un serveur Web simple

Pour commencer très simplement, volons un exemple simple sur le site Node.js. Copiez le code et collez-le dans votre éditeur de code (j'utilise Visual Studio Code, mais tout éditeur qui enregistre du texte brut suffira), puis enregistrez-le sous example.js.

const http = require ('http');

const hostname = '127.0.0.1';

port const = 3000;

serveur de const = http.createServer ((req, res) => {

   res.statusCode = 200;

   res.setHeader ('Content-Type', 'text / plain');

   res.end ('Hello World \ n');

});

server.listen (port, nom d'hôte, () => {

   console.log (`Serveur fonctionnant à // $ {hostname}: $ {port} /`);

});

Ouvrez un shell dans le répertoire où vous avez enregistré le fichier et exécutez le fichier à partir de votre ligne de commande:

$ node example.js

Serveur fonctionnant à //127.0.0.1:3000/

Dans mon cas, j'ai utilisé la fenêtre Terminal dans Visual Studio Code. J'aurais pu presque aussi facilement passer à une fenêtre shell indépendante.

Accédez maintenant à l'URL répertoriée par le serveur:

Appuyez sur Control-C dans le terminal pour arrêter le serveur Node.

Avant de continuer, déchirons le code.

const http = require ('http');

La ligne 1 utilise require, c'est ainsi que vous chargez les modules dans Node.js. L'instruction charge le module http Node.js, qui fournit la createServerméthode appelée aux lignes 6 à 10 et la listenméthode appelée aux lignes 12 à 14. L'opérateur «grosse flèche» =>aux lignes 6 et 12 est un raccourci pour créer des fonctions Lambda anonymes , qui sont fréquemment utilisés dans les applications Node.js.

serveur de const = http.createServer ((req, res) => {

  res.statusCode = 200;

  res.setHeader ('Content-Type', 'text / plain');

  res.end ('Hello World \ n');

});

L' resargument à la createServer()ligne 6 est utilisé pour construire la réponse; l' reqargument contient la requête HTTP entrante, qui est ignorée dans ce code. La res.endméthode définit les données de réponse sur «Hello World \ n» et indique au serveur que la création de la réponse est terminée.

server.listen (port, nom d'hôte, () => {

  console.log (`Serveur fonctionnant à // $ {hostname}: $ {port} /`);

});

La fermeture du serveur produite par la server.listen()méthode indique au serveur d'écouter les requêtes sur l'hôte défini (127.0.0.1, par exemple localhost) et le port (3000). La fermeture produite par la createServer()méthode gère les demandes lorsqu'elles arrivent sur l'hôte et le port définis.

L'idée que les fermetures JavaScript sont définies comme des gestionnaires d'événements est l'une des parties les plus subtiles et les plus puissantes de Node.js, et est une clé de l'architecture asynchrone non bloquante de Node. Node.js masque sa boucle d'événements, mais revient toujours à la gestion des événements lorsqu'il n'est pas activé autrement. En outre, les fermetures JavaScript utilisent beaucoup moins de mémoire que les autres méthodes de gestion de plusieurs connexions client, telles que la création de threads ou les processus de fourche.

Exemple Node.js: un serveur Web multi-processus

Hormis l'impression de «Hello World», l'exemple ci-dessus ne fonctionne que dans un seul thread, ce qui signifie qu'il ne peut utiliser qu'un seul noyau de l'ordinateur hôte. Il y a des moments où vous aurez de nombreux cœurs que vous aimeriez consacrer à un serveur.

L'exemple officiel du module de cluster Node montre comment résoudre ce problème. Comme auparavant, nous volerons le code et l'exécuterons. Accédez à la documentation du cluster Node.js, copiez le code, collez-le dans votre éditeur de code ou IDE et enregistrez-le sous server.js.

const cluster = require ('cluster');

const http = require ('http');

const numCPUs = require ('os'). cpus (). length;

if (cluster.isMaster) {

console.log (`Master $ {process.pid} est en cours d'exécution`);

// Ouvriers à la fourche.

pour (leti = 0; i

cluster.fork ();

}

cluster.on ('exit', (worker, code, signal) => {

console.log (`worker $ {worker.process.pid} est mort`);

});

} autre {

// Les travailleurs peuvent partager n'importe quelle connexion TCP

// Dans ce cas, il s'agit d'un serveur HTTP

http.createServer ((req, res) => {

res.writeHead (200);

res.end (`bonjour le monde de $ {process.pid} \ n`);

}). écouter (8000);

console.log (`Worker $ {process.pid} démarré`);

}

Lorsque vous exécutez à node server.jspartir de votre ligne de commande, le journal affiche les ID de processus pour les processus maître et de travail. Il devrait y avoir autant de travailleurs que votre ordinateur a de cœurs logiques - huit pour mon MacBook Pro avec son processeur Core i7, qui a quatre cœurs matériels et hyper-threading.

Si vous accédez à localhost: 8000 ou à 127.0.0.1:8000, vous verrez «hello world» affiché. Vous pouvez appuyer sur Ctrl-C dans la fenêtre du terminal pour arrêter les processus du serveur Node.

const cluster = require ('cluster');

const http = require ('http');

const numCPUs = require ('os'). cpus (). length;

Les lignes 1 et 2 devraient vous sembler familières d'après le dernier exemple. La ligne 3 est un peu différente. Au lieu de simplement exiger le osmodule, il appelle également la cpus()fonction membre et renvoie la longueur du tableau renvoyé, qui est le nombre de processeurs. Le tableau lui-même et le oslien du module sont alors inaccessibles et peuvent être récupérés ultérieurement par le moteur JavaScript.

if (cluster.isMaster) {

   console.log (`Master $ {process.pid} est en cours d'exécution`);

   // Ouvriers à la fourche.

   pour (soit i = 0; i <nombre de processeurs; i ++) {

      cluster.fork ();

   }

   cluster.on ('exit', (worker, code, signal) => {

      console.log (`worker $ {worker.process.pid} est mort`);

   });

}

La ligne 5 démarre un bloc qui ne s'exécute que pour le processus maître. Il enregistre son PID, effectue des fourches sur le travailleur par CPU disponible et crée une fermeture pour gérer et consigner les événements de sortie du cluster.

} autre {

   // Les travailleurs peuvent partager n'importe quelle connexion TCP

   // Dans ce cas, il s'agit d'un serveur HTTP

   http.createServer ((req, res) => {

      res.writeHead (200);

      res.end ('bonjour le monde \ n');

   }). écouter (8000);

   console.log (`Worker $ {process.pid} démarré`);

Le bloc commençant à la ligne 16 est uniquement exécuté par les processus de travail. Ce code doit sembler familier à partir de l'exemple précédent: il crée un serveur Web qui répond à toute demande par «bonjour le monde».

Il ressort clairement de la sortie que nous avons vue ci-dessus que ce code a été exécuté huit fois sur ma machine, créant huit serveurs Web partageant la connexion TCP du processus parent sur le port 8000. Mais comment le système partage-t-il la charge entre eux?

La documentation indique que le module de cluster Node.js utilise un algorithme circulaire modifié par défaut, sauf sous Windows. L'algorithme est contrôlé par la cluster.schedulingPolicypropriété.

Comment savons-nous que cela fonctionne? Testons-le. Il ne faudra changer qu'une seule ligne de code. Modifiez la ligne 21 pour lire:

      res.end (`bonjour le monde de $ {process.pid} \ n`);

Notez que vous devez non seulement ajouter from ${process.pid}, mais également changer les délimiteurs des guillemets simples aux graduations arrière, de sorte que JavaScript effectue une substitution de variable sur la chaîne.

Enregistrez le fichier, arrêtez toute instance précédente en cours d'exécution et réexécutez-le. Vous pourriez penser que chaque fois que vous actualisez votre navigateur client, l'ID de processus renvoyé changera, mais vous vous trompez. Le navigateur est trop intelligent et nous n'avons pas marqué la page Web comme une page qui expire, de sorte que le navigateur mettra en cache la réponse la première fois qu'il s'exécutera et continuera à afficher le même numéro. Il le fera même si vous créez plusieurs onglets de navigateur ou pages pointant vers la même URL. Cependant, vous pouvez voir que la distribution à tour de rôle à partir du maître fonctionne en exécutant plusieurs navigateurs simultanément, dans ce cas Chrome, Safari et Opera:

Si vous êtes familier avec d'autres serveurs Web, vous pouvez vous attendre à voir un schéma de routage des demandes et de maintien de l'état persistant afin de préserver la connexion et l'environnement de chaque utilisateur dans Node. Hélas, Node n'a pas cela intégré. N'ayez pas peur: il existe de nombreux frameworks Web construits sur Node.js qui font tout ce que vous attendez.

Comment installer un module Node.js avec NPM

Pour utiliser la plupart des modules Node, vous installez simplement le module à partir du registre NPM, soit globalement, soit dans un répertoire de projet, puis require()à partir de votre code. Souvent, un projet dépend de plusieurs modules NPM et conserve cette liste dans son fichier project.json. Au lieu d'installer chaque dépendance à partir de la ligne de commande, vous pouvez les installer toutes en même temps, souvent après avoir extrait le projet de son référentiel GitHub:

$

$ cd mon_projet

Installation de $ npm

Tous les packages NPM ne fonctionnent pas exactement de cette façon. Certains, y compris React, ont des applications «d'usine» pour créer des applications de démarrage comme l'une de leurs options d'installation.

$ npm install -g create-react-app

$ cd ~ / travail

$ create-react-app mon-application

$ cd mon-application /

$ npm début

Il n'est pas rare que des outils soient installés dans le monde entier. Par exemple, l'outil de ligne de commande Angular Ng s'installe globalement. Vous l'exécutez ensuite localement pour créer une application dans un dossier.

$ npm install -g @ angulaire / cli

$ cd ~ / travail

$ ng nouvelle my-app

Angular a une autre méthode d'installation qui ressemble plus au modèle standard. C'est pour la graine Angular QuickStart:

$ git clone //github.com/angular/quickstart.git démarrage rapide

$ cd démarrage rapide

Installation de $ npm

Le fichier package.json dans le dossier de démarrage rapide indique npm installde récupérer presque la même liste de dépendances que l'installation CLI.

Exemple Node.js: un serveur Web Koa

Bien que React et Angular fassent tous deux partie de l'écosystème Node.js et nécessitent Node.js et NPM pour le développement, ils ne sont pas spécifiquement des frameworks Node.js - ils peuvent s'exécuter dans un navigateur. J'ai couvert des dizaines de frameworks Node.js réels dans le «Guide complet des frameworks Node.js».

Par exemple, Express est le serveur Web Node original, qui gère l'application Web, les requêtes et réponses HTTP, le routage et le middleware. Une option plus récente, Koa, utilise des générateurs au lieu de rappels pour le middleware.

Vous installez Koa avec le modèle standard dans le dossier de votre application:

$ npm installer koa  

Vous trouverez ci-dessous le code de l'application Koa «Hello World», que vous pouvez enregistrer et exécuter comme dans les exemples précédents.

const Koa = require ('koa');

const app = nouveau Koa ();

// temps de réponse x

app.use (async (ctx, suivant) => {

const start = Date.now ();

attendre suivant ();

const ms = Date.now () -start;

ctx.set ('X-Response-Time', `$ {ms} ms`);

});

// enregistreur

app.use (async (ctx, suivant) => {

const start = Date.now ();

attendre suivant ();

const ms = Date.now () -start;

console.log (`$ {ctx.method} $ {ctx.url} - $ {ms}`);

});

// réponse

app.use (async ctx => {

ctx.body = 'Bonjour le monde';

});

app.listen (3000);

Il existe une différence entre les générateurs middleware utilisés par Koa et les rappels utilisés par Express et d'autres frameworks Node.js. De nombreuses implémentations de rappel passent simplement le contrôle à travers une série de fonctions jusqu'à ce que l'une d'entre elles revienne, tandis que Koa donne «en aval», puis contrôle les flux de retour «en amont».

Dans l'exemple ci-dessus, le temps de réponse x «encapsule» le générateur de réponse, avec l'  await next() instruction marquant l'appel. L'utilisation de cette fonction asynchrone est plus flexible que les appels de fonction explicites, car elle facilite l'insertion d'un autre générateur dans la séquence, par exemple un enregistreur Web entre le minuteur et la réponse.

Vous pourriez rencontrer un ancien code Koa qui utilise à la yield nextplace de await next(). La différence est que Koa prend désormais en charge les fonctions ES2015 et async. Le flux de contrôle revient au même: il passe au gestionnaire suivant de la chaîne lors de l' yield nextappel, puis revient lorsque tous les gestionnaires ont terminé.