Mis à jour le mardi 2 janvier 2018
  • 10 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Les modules Node.js et NPM

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Croyez-le ou non, le noyau de Node.js est tout petit. De base, Node.js ne sait en fait pas faire grand chose.

Pourtant, Node.js est très riche grâce à son extensibilité. Ces extensions de Node.js sont appelées modules.

Il existe des milliers de modules qui offrent des fonctionnalités variées : de la gestion des fichiers uploadés à la connexion aux bases de données MySQL ou à Redis, en passant par des frameworks, des systèmes de templates et la gestion de la communication temps réel avec le visiteur ! Il y a à peu près tout ce dont on peut rêver et de nouveaux modules apparaissent chaque jour.

Nous allons commencer par voir comment sont gérés les modules par Node.js et nous verrons que nous pouvons facilement en créer un nous aussi. Puis, nous découvrirons NPM (Node Package Manager), l'outil indispensable qui vous permet de télécharger facilement tous les modules de la communauté Node.js ! Enfin, je vous montrerai comment accéder à la gloire éternelle en publiant votre module sur NPM. :soleil:

Créer des modules

Vous souvenez-vous de cette ligne ?

var http = require('http');

Elle était tout au début de notre premier code. Je vous avais dit que c'était un appel à la bibliothèque "http" de Node.js (ou devrais-je dire au module "http").

Quand on fait ça, Node.js va chercher sur notre disque un fichier appeléhttp.js. De même, si on demande le module "url", Node.js va rechercher un fichier appelé url.js.

var http = require('http'); // Fait appel à http.js
var url = require('url'); // Fait appel à url.js

Où sont ces fichiers .js ? Je ne les vois pas !

Ils sont quelque part bien au chaud sur votre disque, leur position ne nous intéresse pas. ;)
Etant donné qu'ils font partie du noyau de Node.js, ils sont tout le temps disponibles.

Les modules sont donc de simples fichiers .js. Si nous voulons créer un module, disons le module "test", nous devons créer un fichier test.js dans le même dossier et y faire appel comme ceci :

var test = require('./test'); // Fait appel à test.js (même dossier)

C'est un chemin relatif. Si le module se trouve dans le dossier parent, nous pouvons l'inclure comme ceci :

var test = require('../test'); // Fait appel à test.js (dossier parent)

Et si je ne veux pas mettre de chemin relatif ? Je ne peux pas juste fairerequire('test')?

Si vous pouvez ! Il faut mettre votre fichier test.js dans un sous-dossier appelé "node_modules". C'est une convention de Node.js :

var test = require('test'); // Fait appel à test.js (sous-dossier node_modules)

En résumé :

Node.js sait où chercher les modules
Node.js sait où chercher les modules

Notez que si le dossier node_modules n'existe pas, Node.js ira chercher un dossier qui a le même nom plus haut dans l'arborescence. Ainsi, si votre projet se trouve dans le dossier : /home/mateo21/dev/nodejs/projet, il ira chercher un dossier nommé :

  • /home/mateo21/dev/nodejs/projet/node_modules, et si ce dossier n'existe pas il ira le chercher dans...

  • ... /home/mateo21/dev/nodejs/node_modules, et si ce dossier n'existe pas il ira le chercher dans...

  • ... /home/mateo21/dev/node_modules, et ainsi de suite !

A quoi ressemble le code des fichiers .js des modules ?

C'est du code JavaScript tout ce qu'il y a de plus classique. Vous y créez des fonctions.
Une seule particularité : vous devez "exporter" les fonctions que vous voulez que d'autres personnes puissent réutiliser.

Testons ça ! On va créer un module tout bête qui sait dire "Bonjour !" et "Bye bye !". Créez un fichier monmodule.js avec le code suivant :

var direBonjour = function() {
    console.log('Bonjour !');
}

var direByeBye = function() {
    console.log('Bye bye !');
}

exports.direBonjour = direBonjour;
exports.direByeBye = direByeBye;

Le début du fichier ne contient rien de nouveau. Nous créons des fonctions que nous plaçons dans des variables. D'où levar direBonjour = function()...

Ensuite, et c'est la nouveauté, nous exportons ces fonctions pour qu'elles soient utilisables de l'extérieur :exports.direBonjour = direBonjour;. Notez d'ailleurs qu'on aurait aussi pu faire directement :

exports.direBonjour = function() { ... };

Maintenant, dans le fichier principal de votre application (ex : app.js), vous pouvez faire appel à ces fonctions issues du module !

var monmodule = require('./monmodule');

monmodule.direBonjour();
monmodule.direByeBye();

require()renvoie en fait un objet qui contient les fonctions que vous avez exportées dans votre module. Nous stockons cet objet dans une variable du même nommonmodule(mais on aurait pu lui donner n'importe quel autre nom).

Exportation d'une fonction
Exportation d'une fonction

Voilà, vous savez tout ! Tous les modules de Node.js sont basés sur ce principe très simple. :)

Cela vous permet de découper votre projet en plusieurs petits fichiers pour répartir les rôles.

Utiliser NPM pour installer des modules

Je vous ai parlé en introduction de NPM (le Node Package Manager). Je vous ai dit que c'était un moyen (formidable) d'installer de nouveaux modules développés par la communauté.

Imaginez que NPM est un peu l'équivalent d'apt-get sous Linux pour installer des programmes. Une simple commande et le module est téléchargé et installé !
En plus, NPM gère les dépendances. Cela signifie que, si un module a besoin d'un autre module pour fonctionner, NPM ira le télécharger automatiquement !

NPM possède un site web : http://npmjs.org !

Le site web de NPM
Le site web de NPM

Comme vous pouvez le voir, NPM est très actif. Il y a plusieurs dizaines de milliers de modules disponibles, et on compte plusieurs millions de téléchargements par semaine ! Si vous n'y trouvez pas votre bonheur, c'est que vous le faites exprès. :D

Comme le dit le site web de NPM, il est aussi simple d'installer de nouveaux modules que de publier ses propres modules. C'est en bonne partie ce qui explique le grand succès de Node.js.

Comment trouver un module là-dedans ? Autant chercher une aiguille dans une botte de foin ! :(

C'est assez facile en fait. Je vais vous montrer plusieurs moyens de trouver des modules !

Trouver un module

Si vous savez ce que vous cherchez, le site web de NPM vous permet de faire une recherche. Mais NPM, c'est avant tout une commande ! Vous pouvez faire une recherche dans la console, comme ceci :

npm search postgresql

... ce qui aura pour effet de rechercher tous les modules en rapport avec la base de données PostgreSQL par exemple.

Installer un module

Pour installer un module, rien de plus simple. Placez-vous dans le dossier de votre projet et tapez :

npm install nomdumodule

Le module sera installé localement spécialement pour votre projet.
Si vous avez un autre projet, il faudra donc relancer la commande pour l'installer à nouveau pour cet autre projet. Cela vous permet d'utiliser des versions différentes d'un même module en fonction de vos projets.

Allez faisons un test. On va installer le module markdown qui permet de convertir du code markdown en HTML.

npm install markdown

NPM va télécharger automatiquement la dernière version du module et il va la placer dans un sous-dossier node_modules. Vérifiez donc bien que vous êtes dans le dossier de votre projet Node.js avant de lancer cette commande !

Une fois que c'est fait, vous avez accès aux fonctions offertes par le module markdown. Lisez la doc du module pour savoir comment l'utiliser. On nous apprend qu'il faut faire appel à l'objet markdown à l'intérieur du module et qu'on peut appeler la fonction toHTML pour traduire du Markdown en HTML.

Essayons ça :

var markdown = require('markdown').markdown;

console.log(markdown.toHTML('Un paragraphe en **markdown** !'));

... affichera dans la console :

<p>Un paragraphe en <strong>markdown</strong> !</p>

L'installation locale et l'installation globale

NPM installe les modules localement pour chaque projet. C'est pour cela qu'il crée un sous-dossier node_modules à l'intérieur de votre projet.
Si vous utilisez le même module dans 3 projets différents, il sera téléchargé et copié 3 fois. C'est normal, cela nous permet de gérer les différences de version. C'est donc une bonne chose.

Par contre, il faut savoir que NPM permet aussi d'installer des modules globaux. Ca ne nous sert que dans de rares cas où le module fournit des exécutables (et pas juste des fichiers .js).

C'est le cas de notre module markdown par exemple. Pour l'installer globalement, on va ajouter le paramètre -g à la commande npm :

npm install markdown -g

Vous aurez alors accès à un exécutable md2html dans votre console :

echo 'Hello *World*!' | md2html

Mettre à jour les modules

Avec une simple commande :

npm update

... NPM va chercher sur les serveurs s'il y a de nouvelles versions des modules, puis mettre à jour les modules installés sur votre machine (en veillant à ne pas casser la compatibilité) et il supprimera les anciennes versions. Bref, c'est la commande magique. :D

Déclarer et publier son module

Si votre programme a besoin de modules externes, vous pouvez les installer un à un comme vous venez d'apprendre à le faire... mais vous allez voir que ça va vite devenir assez compliqué à maintenir. C'est d'autant plus vrai si vous utilisez de nombreux modules. Comme ces modules évoluent de version en version, votre programme pourrait devenir incompatible suite à une mise à jour d'un module externe !

Heureusement, on peut régler tout ça en définissant les dépendances de notre programme dans un simple fichier JSON. C'est un peu la carte d'identité de notre application.

Créez un fichierpackage.jsondans le même dossier que votre application. Commençons simplement avec ce code :

{
    "name": "mon-app",
    "version": "0.1.0",
    "dependencies": {
        "markdown": "~0.4"
    }
}

Ce fichier JSON contient 3 paires clé-valeur :

  • name : c'est le nom de votre application. Restez simple, évitez espaces et accents.

  • version : c'est le numéro de version de votre application. Il est composé d'un numéro de version majeure, de version mineure et de patch. J'y reviens juste après.

  • dependencies : c'est un tableau listant les noms des modules dont a besoin votre application pour fonctionner ainsi que les versions compatibles.

Le fonctionnement des numéros de version

Pour bien gérer les dépendances et savoir mettre à jour le numéro de version de son application, il faut savoir comment fonctionnent les numéros de version avec Node.js. Il y a pour chaque application :

  • Un numéro de version majeure. En général on commence à 0 tant que l'application n'est pas considérée comme mature. Ce numéro change très rarement, uniquement quand l'application a subi des changements très profonds.

  • Un numéro de version mineure. Ce numéro est changé à chaque fois que l'application est un peu modifiée.

  • Un numéro de patch. Ce numéro est changé à chaque petite correction de bug ou de faille. Les fonctionnalités de l'application restent les mêmes entre les patchs, il s'agit surtout d'optimisations et de corrections indispensables.

Les numéros de version d'une application Node.js
Les numéros de version d'une application Node.js

Ici j'ai donc choisi de commencer à numéroter mon application à la version 0.1.0 (on aurait aussi pu commencer à 1.0.0 mais ç'aurait été prétentieux ;) ).

  • Si je corrige un bug, l'application passera à la version 0.1.1 et il me faudra mettre à jour ce numéro dans le fichier packages.json.

  • Si j'améliore significativement mon application, elle passera à la version 0.2.0, puis 0.3.0 et ainsi de suite.

  • Le jour où je considère qu'elle a atteint un jalon important, et qu'elle est mature, je pourrai la passer en version 1.0.0.

La gestion des versions des dépendances

C'est à vous d'indiquer avec quelles versions de ses dépendances votre application fonctionne. Si votre application dépend du module markdown v0.3.5 très précisément, vous écrirez :

"dependencies": {
    "markdown": "0.3.5" // Version 0.3.5 uniquement
}

Si vous faites un npm update pour mettre à jour les modules externes, markdown ne sera jamais mis à jour (même si l'application passe en version 0.3.6). Vous pouvez mettre un tilde devant le numéro de version pour autoriser les mises à jour jusqu'à la prochaine version mineure :

"dependencies": {
    "markdown": "~0.3.5" // OK pour les versions 0.3.5, 0.3.6, 0.3.7, etc. jusqu'à la version 0.4.0 non incluse
}

Si vous voulez, vous pouvez ne pas indiquer de numéro de patch. Dans ce cas, les modules seront mis à jour même si l'application change de version mineure :

"dependencies": {
    "markdown": "~0.3" // OK pour les versions 0.3.X, 0.4.X, 0.5.X jusqu'à la version 1.0.0 non incluse
}

Attention néanmoins : entre deux versions mineures, un module peut changer suffisamment et votre application pourrait être incompatible. Je recommande d'accepter uniquement les mises à jour de patch, c'est le plus sûr.

Publier un module

Avec Node.js, vous pouvez créer une application pour vos besoins, mais vous pouvez aussi créer des modules qui offrent des fonctionnalités. Si vous pensez que votre module pourrait servir à d'autres personnes, n'hésitez pas à le partager ! Vous pouvez très facilement le publier sur NPM pour que d'autres personnes puissent l'installer à leur tour.

Vous voulez accéder à la gloire éternelle et voir votre module téléchargé des milliers de fois sur NPM ? Rien de plus simple ! :D

Commencez par vous créer un compte utilisateur sur npm :

npm adduser

Une fois que c'est fait, placez-vous dans le répertoire de votre projet à publier. Vérifiez que vous avez :

  • Un fichier package.json qui décrit votre module (au moins son nom, sa version et ses dépendances)

  • Un fichier README.md (écrit en markdown) qui présente votre module de façon un peu détaillée. N'hésitez pas à y inclure un mini-tutoriel expliquant comment utiliser votre module !

Il ne vous reste plus qu'à faire :

npm publish

Et voilà, c'est fait ! :D

Il ne vous reste plus qu'à parler de votre module autour de vous, le présenter sur les mailing-lists de Node.js... Les portes de la gloire des geeks barbus vous attendent !

Votre module est publié, à vous la gloire !
Votre module est publié, à vous la gloire !
Exemple de certificat de réussite
Exemple de certificat de réussite