Npx vs npm : le guide pratique pour ne plus confondre installation et exécution

Dans l’écosystème Node.js, npm et npx coexistent depuis que npx a été intégré à npm à partir de la version 5.2. Les deux commandes partagent le même registre de packages, le même fichier de configuration, et pourtant leur comportement diverge sur un point fondamental : npm installe, npx exécute. Cette distinction, simple en apparence, implique des conséquences concrètes sur la structure d’un projet, la gestion du cache et la surface d’exposition aux risques liés aux scripts d’installation.

Ce que npm fait réellement quand vous l’invoquez

npm est un gestionnaire de paquets : son rôle principal est de résoudre, télécharger et ancrer des dépendances dans un projet. Quand vous lancez npm install lodash, npm télécharge le package depuis le registre, le place dans le dossier node_modules et enregistre la dépendance dans package.json. Cette trace est permanente.

L’installation globale avec le flag -g fonctionne selon la même logique, mais écrit le binaire dans un répertoire système accessible depuis n’importe quel chemin. C’est pratique pour des outils utilisés quotidiennement, mais cela crée une dépendance implicite entre la machine du développeur et les projets qu’elle héberge.

npm gère aussi l’exécution de scripts via npm run, en lisant la section scripts du package.json. Ces deux fonctions – gestion des dépendances et exécution de scripts déclarés – couvrent la majorité des besoins d’un projet standard.

npx est une interface vers npm exec, pas un outil indépendant

C’est un point que les guides introductifs passent souvent sous silence : depuis npm 7, npx est réécrit comme interface vers npm exec. L’ancien paquet autonome npx est officiellement déprécié. Invoquer npx create-react-app mon-projet revient aujourd’hui à appeler npm exec -- create-react-app mon-projet, avec quelques différences dans la gestion des options.

Cette évolution a une implication pratique sur la syntaxe. Avec npm exec, le séparateur -- permet de transmettre clairement les arguments à la commande exécutée, évitant toute ambiguïté avec les flags de npm lui-même. Avec npx, les options propres à npx doivent précéder les arguments positionnels. Pour des commandes simples, la différence est invisible ; pour des commandes avec plusieurs arguments, elle peut produire des comportements inattendus.

Développeuse en espace de coworking comparant les commandes npm install et npx sur son ordinateur portable avec deux terminaux ouverts

Ce que npx télécharge – et ce qu’il exécute

Quand le binaire demandé n’existe pas dans les dépendances locales du projet, npx le récupère depuis le registre npm et l’ajoute temporairement au PATH de la commande. Ce comportement ressemble à une installation classique sur un point précis : la récupération du package peut déclencher des scripts de cycle de vie (notamment postinstall).

Les versions modernes de npx affichent un prompt de confirmation avant d’exécuter un package absent du projet. Ce prompt peut être supprimé avec le flag --yes, ce qui restaure le comportement automatique des premières versions. Pour des environnements CI/CD où la confirmation interactive est impossible, ce flag est souvent nécessaire, mais il neutralise la protection.

Une autre limite concerne la reproductibilité. Le cache utilisé par npm exec n’est pas une méthode d’installation fiable sur le long terme : rien ne garantit qu’un package y restera disponible entre deux exécutions. Pour des commandes répétées avec une version précise, il vaut mieux spécifier la version explicitement (npx [email protected]) ou déclarer l’outil comme dépendance du projet.

Quand utiliser npm install et quand préférer npx

La question n’est pas tant « quel outil est meilleur » que « quel comportement correspond à l’usage prévu ». Quelques repères concrets :

  • npm install est adapté quand le package fait partie du projet : une librairie utilisée dans le code source, un outil de build lancé à chaque développement. La dépendance doit apparaître dans package.json pour être reproductible sur une autre machine.
  • npx est adapté pour les commandes ponctuelles : initialiser un projet avec un générateur (create-react-app, create-next-app), tester une version spécifique d’un outil CLI sans écraser la version installée, ou lancer un utilitaire sans l’ancrer dans le projet.
  • npm install -g reste pertinent pour des outils utilisés en dehors de tout projet spécifique, mais sa pertinence diminue à mesure que npx couvre les mêmes cas sans polluer l’environnement global.

Un cas fréquent d’erreur : utiliser npm install create-react-app -g pour ensuite lancer create-react-app mon-projet. Cette approche installe une version figée de l’outil en global ; si le projet a évolué, la version locale reste derrière. npx create-react-app mon-projet récupère toujours la dernière version disponible au moment de l’exécution, sauf si une version est explicitement précisée.

npm et npx dans un même workflow : les patterns courants

Les deux outils ne s’excluent pas. Dans un projet React typique, npx create-react-app initialise le projet une seule fois, puis npm install gère toutes les dépendances ajoutées ensuite. Les scripts de développement et de build sont déclarés dans package.json et exécutés via npm run.

Un pattern moins documenté : utiliser npx pour lancer des binaires installés localement dans node_modules/.bin. Si eslint est une dépendance du projet, npx eslint src/ le trouve sans avoir à écrire ./node_modules/.bin/eslint. npm résout d’abord les dépendances locales avant de chercher dans le cache ou le registre distant.

  • Lancer un binaire local sans chemin absolu : npx eslint . ou npx prettier --write .
  • Tester une version alternative d’un outil : npx webpack@4 --config webpack.config.js
  • Exécuter un script de migration ou de scaffolding une seule fois : npx prisma migrate dev

Dans tous ces cas, npx agit comme un résolveur de contexte d’exécution, pas comme un gestionnaire de dépendances. La distinction reste la même : npm ancre, npx exécute sans ancrer.

La confusion entre les deux commandes vient souvent d’une même interface en ligne de commande et d’un même registre sous-jacent. Mais l’intention de chaque outil est lisible dans son nom : Node Package Manager d’un côté, Node Package Execute de l’autre. Comprendre que npx est aujourd’hui une surcouche de npm exec – et non un outil autonome – clarifie aussi pourquoi ses comportements évoluent au rythme de npm.