Comment changer de version de Node.js avec NVM ?

Vous voulez changer rapidement de version de node ? nvm est l’outil qu’il vous faut.

Premiers pas

Pourquoi nvm ? node est un exécutable. Par exemple, sous Linux, si vous avez installé le paquet de votre distribution, il sera présent dans un répertoire du type /usr/local/bin.
Le problème est que cet exécutable correspond à une version donnée et fixe, et ne peut être mis à jour que vers une version plus récente par votre gestionnaire de paquets.
nvm vous permet en revanche de faire coexister plusieurs versions sur la même machine.

1. Installation

nvm dispose de plusieurs méthodes d’installation, dont un script pour l’installer automatiquement. À la date de publication de cet article, vous pouvez lancer (voir le README) : 
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
Ce script installera nvm dans ~/.nvm et ajoutera des lignes au fichier de configuration de votre shell qui doivent être exécutées pour que nvm puisse fonctionner. Pour utiliser nvm, ouvrez un nouveau shell ou exécutez la commande source [fichier] où [fichier] est le script de configuration de votre shell (~/.bashrc, ~/.zshrc ou autre selon votre cas)
Vous pouvez voir la liste des versions de node disponibles au téléchargement en lançant
nvm ls-remote.

2. Utilisation

Nous allons installer deux versions de node différentes :
nvm install 12.16.3
Un node -v vous indique que l'exécutable est à la version 12.16.3.
nvm install 14.3.0
Un node -v vous indique que l'exécutable est à la version 14.3.0, et si cette version est celle dont vous avez besoin pour votre projet, vous pouvez directement le lancer !
Vous pouvez ensuite librement changer de version en utilisant nvm use [numéro de version].
Pour mieux comprendre la magie derrière nvm, explorons la structure du dossier d’installation.

Comment ça marche

Le script d’installation a cloné le répertoire git dans ~/.nvm.
ls ~/.nvm
Le dossier le plus important en pratique est celui appelé versions/node, qui stocke dans des dossiers différents les versions installées et les fait coexister.
cd ~/.nvm/versions/node
Vous devriez voir apparaître la structure suivante :
La structure du sous-dossier ~/.nvm/versions/node
Dans chaque sous-dossier, il y a un répertoire bin qui regroupe les exécutables correspondant à la version en question (npm et npx sont des liens symboliques).
Vous pouvez désormais vérifier que  ./v12.16.3/bin/node -v et ./v14.3.0/bin/node -v vous donnent les numéros de version attendus.
Vous pouvez retrouver ces chemins d’installation en lançant : 
nvm which current
nvm which 12.16.3

Changez encore plus rapidement de version

Si vous travaillez sur de nombreux projets et que vous vous perdez dans les numéros de version, les alias suivants devraient vous faciliter la vie :
nvm alias project1 12.16.3
nvm alias project2 14.3.0
Vous pouvez maintenant changer directement de version avec nvm use project1 et nvm use project2.
Il existe des alias utiles déjà configurés, que vous pouvez voir en tapant nvm alias puis tabulation dans le terminal :
  • lts/* : la dernière version stable
  • node : la dernière version
Si vous souhaitez ne rien écrire du tout, c'est aussi possible ! Placez un fichier .nvmrc à la racine de votre projet et utilisez nvm use, nvm install sans préciser de version à l'intérieur de celui-ci.

Les versions dans l’univers Node.js

Vous avez peut-être remarqué que les versions de node et npm sont de la forme suivante :
X.Y.Z
Et ce n’est pas un hasard que ce format soit aussi celui de vos paquets dans votre package.json et package-lock.json.
Du doux nom de semver, la gestion sémantique de version est au cœur de l’écosystème et tout développeur JavaScript gagnerait à la maîtriser.
Le premier nombre “X” correspond à la version majeure : lorsque ce nombre est incrémenté, cela indique que la nouvelle version n’est pas rétro-compatible avec la version précédente.
Le deuxième, “Y”, correspond à la version mineure. Un changement indique que plus de fonctions sont disponibles ou que certaines sont obsolètes, mais que l’API reste rétrocompatible. La version “Z” indique une correction de bugs.
On doit revenir à zéro pour “Z” quand on incrémente “Y”, et on doit mettre à zero “Y” et “Z” quand on incrémente “X”.
Attention cependant, rien n’empêche un développeur d’incrémenter “X” ou “Y” en mettant en ligne leur paquet npm, et malheureusement, l’erreur est humaine.
Si vous voulez approfondir, vous pouvez consulter la norme "Semantic Versioning".

Un petit détour dans le package.json

Dans votre package.json, vous avez sûrement déjà vu ces numéros de version agrémentées de décorations : “^4.12.2”, “<=12.0.1”, “~0.4.77” ou pas, comme dans “1.0.3”. Parfois même, vous y voyez des arrangements compliqués : “<1.0.0 || >=2.5.1” ou encore “>4.0.1 <=5.3.0”.
Voici la traduction : 
  • 1.0.3 : npm doit installer la version 1.0.3, et aucune latitude ne lui est laissée ;
  • ^4.12.2 : npm doit installer la version ayant la version la plus à jour après la 4.12.2 incluse, mais pas celle après 5.0.0. En gros, pas de version qui n’est pas rétrocompatible avec la 4.12.2 ;
  • ~0.4.77 : npm doit installer la dernière version 0.4.x ;
  • <=12.0.1 : soit la version 12.0.1 si elle existe, soit une version précédente. Ça peut être utile pour laisser le choix à npm, par exemple si un autre paquet requiert ce package à la version 11.0.6.
  • “<1.0.0 || >=2.5.1” : toutes les versions sauf celles entre la 1.0.0 et la 2.5.0 (dont l’API ne nous convient peut-être pas).
  • “>4.0.1 <=5.3.0” : toutes les versions entre la 4.0.2 et la 5.3.0 incluses.
Si ces exemples n'ont pas étanché votre intense curiosité, vous pouvez vous pencher sur le parseur de npm.

Les versions de node

node est un exécutable dont les versions suivent le “Semantic versioning”.
Son cycle de release est très régulier puisqu'une nouvelle version majeure est créée tous les 6 mois.
Les versions majeures impaires (13.*.*, 15.*.*, etc.) sont abandonnées au bout de 6 mois. Les versions majeures paires (14.*.*, 16.*.*, etc.) ont un sort différent au bout de ces 6 mois :
  • elles sont mises en support long-terme (LTS), support qui dure 12 mois. Des mises à jour et des résolutions de bugs peuvent avoir lieu ;
  • à la fin de cette période, elles sont maintenues pendant 18 mois supplémentaires, au cours desquels les bugs sont résolus.
Morale de l’histoire, si vous démarrez un projet ou si vous mettez à jour sa version, préférez la version majeure paire actuelle de node.
Plus d'informations sur ce cycle sur la page consacŕee du répertoire de node.

Les erreurs dues aux versions de node

Supposons que si vous exécutez npm install, npm se plaigne en écrivant :
npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE   package: '@angular-devkit/core@x.y.z', npm WARN EBADENGINE   required: { node: '>= 12.4.0 <12.9.1', npm: '^6.10.0 || ^7.5.6',}, npm WARN EBADENGINE   current: { node: 'v18.18.0', npm: '9.8.1' } npm WARN EBADENGINE }
On devrait donc avoir : 
  • une version de node doit être supérieure à 12.4.0 inclus et inférieure à 12.9.0 inclus (actuellement, ce n'est pas le cas, puisque npm est à la version 18.18.0)
  • une version de npm entre 6.10.0 inclus et 7.0.0 exclu ou entre 7.5.6 inclus et 8.0.0 exclu (actuellement, ce n’est pas le cas, puisque npm est à la version 9.8.1).
Un petit détour par nvm ls-remote m’indique les versions possibles après la 12.4.0.
nvm use 12.4.0 m’indique que cette version vient avec npm version 6.9.0, ce qui ne convient pas selon mon message d’erreur.
Après quelques installations, je m’aperçois que la version 12.7.0 de node convient et résout mon message d’erreur.
Je peux désinstaller les versions inutiles en utilisant nvm uninstall [version].

Conclusion

nvm est un utilitaire qui peut se montrer très utile si vous ne maîtrisez pas la version de node sur le serveur, si vous travaillez sur un projet où sa mise à jour impromptue serait malvenue par rapport aux autres collaborateurs, ou encore si cette dernière casserait certains vieux paquets. Il existe d'autres gestionnaires de versions de node comme n (disponible ici), mais le nombre de versions est plus restreint.
Vous souhaitez être accompagné pour lancer votre projet digital ?
Déposez votre projet dès maintenant
Next.js App Router : le cache et ses dangers
“Il y a seulement 2 problèmes compliqués en informatique : nommer les choses, et l’invalidation de cache”. Phil Karlton. Avec ...
Valentin Gerest
Valentin Gerest
Full-Stack Developer @ Galadrim
Qu'est-ce que le SMS pumping et comment s'en protéger ?
La fraude appelée SMS pumping survient lorsque des fraudeurs exploitent un champ de saisie de numéro de téléphone de votre ...
Arnaud Albalat
Arnaud Albalat
CTO @ Galadrim
Les Normes RGAA et l’accessibilité numérique
En France, 90 % de la population, parmi lesquels se trouvent vos clients, se connectent à des sites web et des contenus en ...
Arnaud Albalat
Arnaud Albalat
CTO @ Galadrim