Debutant 10 min de lecture · 2 156 mots

NPM et Node.js : Gérer les dépendances de projet

Estimated reading time: 10 minutes

Introduction

NPM (Node Package Manager) est l’écosystème de packages le plus vaste au monde avec plus de 2 millions de packages. Comprendre comment gérer les dépendances est crucial pour tout développeur JavaScript moderne.

1. Node.js et NPM : Les bases

Installation de Node.js

# Vérifier la version installée
node --version  # v20.10.0 (LTS 2025)
npm --version   # 10.2.5

# Avec nvm (Node Version Manager) - Recommandé
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Installer la dernière version LTS
nvm install --lts
nvm use --lts

# Lister les versions installées
nvm ls

# Passer d'une version à l'autre
nvm use 20
nvm use 18

Gestionnaires de packages en 2025

Gestionnaire Vitesse Espace disque Workspaces Recommandé pour
npm Moyen Élevé Oui Projets standards
pnpm Rapide Faible Oui Monorepos, performance
yarn Rapide Moyen Oui Projets complexes
bun Très rapide Faible Oui Projets modernes
# Installer les alternatives
npm install -g pnpm
npm install -g yarn
curl -fsSL https://bun.sh/install | bash

2. package.json : Le coeur du projet

Créer un nouveau projet

# Initialisation interactive
npm init

# Initialisation avec valeurs par défaut
npm init -y

# Avec pnpm
pnpm init

# Avec scope (organisation)
npm init --scope=@monentreprise

Structure de package.json

{
  "name": "mon-app-react",
  "version": "1.0.0",
  "description": "Une application React moderne",
  "type": "module",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "test": "vitest",
    "test:ui": "vitest --ui",
    "lint": "eslint src --ext ts,tsx",
    "format": "prettier --write "src//.{ts,tsx}"",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/react": "^18.3.5",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "typescript": "^5.6.2",
    "vite": "^5.4.7",
    "vitest": "^2.0.5"
  },
  "engines": {
    "node": ">=20.0.0",
    "npm": ">=10.0.0"
  },
  "packageManager": "pnpm@9.12.0"
}

Champs importants expliqués

{
  // Type de module (ESM par défaut en 2025)
  "type": "module",

  // Exports publics du package
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./utils": "./dist/utils.js"
  },

  // Fichiers à inclure dans le package publié
  "files": [
    "dist",
    "README.md"
  ],

  // Mots-clés pour la recherche NPM
  "keywords": [
    "react",
    "components",
    "ui"
  ],

  // Licence
  "license": "MIT",

  // Repository
  "repository": {
    "type": "git",
    "url": "https://github.com/username/repo.git"
  },

  // Auteur
  "author": {
    "name": "Votre Nom",
    "email": "email@example.com",
    "url": "https://votresite.com"
  }
}

3. Gestion des dépendances

Installer des packages

# Production dependency
npm install react
npm i react  # raccourci

# Development dependency
npm install -D vite
npm install --save-dev vite

# Version spécifique
npm install react@18.3.1

# Version avec range
npm install react@^18.0.0  # Compatible avec 18.x.x
npm install react@~18.3.0  # Compatible avec 18.3.x

# Dernière version
npm install react@latest

# Version alpha/beta
npm install react@next

# Installer toutes les dépendances
npm install

# Avec pnpm (plus rapide)
pnpm install react
pnpm add -D vite

Comprendre les versions (SemVer)

Version: MAJOR.MINOR.PATCH
Example: 2.4.7

MAJOR: Breaking changes (2.0.0 → 3.0.0)
MINOR: Nouvelles features (2.4.0 → 2.5.0)
PATCH: Bug fixes (2.4.7 → 2.4.8)
{
  "dependencies": {
    "react": "18.3.1",        // Version exacte
    "react": "^18.3.1",       // >=18.3.1 <19.0.0 (défaut)
    "react": "~18.3.1",       // >=18.3.1 <18.4.0
    "react": ">=18.3.1",      // Toute version >= 18.3.1
    "react": "",             // N'importe quelle version (déconseillé)
    "react": "latest"         // Dernière version (déconseillé)
  }
}

Mettre à jour les dépendances

# Vérifier les packages obsolètes
npm outdated

# Mettre à jour un package
npm update react

# Mettre à jour tous les packages (respecte semver)
npm update

# Mettre à jour vers la dernière version (ignore semver)
npm install react@latest

# Outil interactif (recommandé)
npx npm-check-updates -i
npx npm-check-updates -u  # Met à jour package.json

# Avec pnpm
pnpm update
pnpm update --latest

Désinstaller des packages

# Supprimer un package
npm uninstall react
npm rm react  # raccourci

# Supprimer et retirer de package.json
npm uninstall react --save

# Nettoyer les dépendances inutilisées
npm prune

# Avec pnpm
pnpm remove react

4. package-lock.json et lockfiles

Pourquoi les lockfiles ?

# package.json
"react": "^18.3.1"  # Peut installer 18.3.1, 18.3.2, 18.4.0...

# package-lock.json verrouille la version exacte
"react": {
  "version": "18.3.1",
  "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
  "integrity": "sha512-..."
}

Lockfiles par gestionnaire

# NPM
package-lock.json

# pnpm (plus efficace)
pnpm-lock.yaml

# Yarn
yarn.lock

# Bun
bun.lockb

Bonnes pratiques

# ✅ Toujours commiter les lockfiles
git add package-lock.json
git commit -m "Update dependencies"

# ✅ Utiliser la même commande que celle du lockfile
# Si package-lock.json existe → npm install
# Si pnpm-lock.yaml existe → pnpm install

# ❌ Ne jamais modifier manuellement les lockfiles

# Régénérer un lockfile corrompu
rm package-lock.json
npm install

5. Scripts NPM

Scripts courants

{
  "scripts": {
    // Développement
    "dev": "vite",
    "start": "vite",

    // Build
    "build": "tsc && vite build",
    "build:prod": "NODEENV=production npm run build",

    // Preview
    "preview": "vite preview",

    // Tests
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:coverage": "vitest --coverage",
    "test:ui": "vitest --ui",

    // Linting & Formatting
    "lint": "eslint src --ext ts,tsx",
    "lint:fix": "eslint src --ext ts,tsx --fix",
    "format": "prettier --write "src//.{ts,tsx,css}"",
    "format:check": "prettier --check "src//.{ts,tsx,css}"",

    // Type checking
    "type-check": "tsc --noEmit",

    // Pre-commit (avec husky)
    "pre-commit": "lint-staged",

    // CI/CD
    "ci": "npm run type-check && npm run lint && npm run test",

    // Nettoyage
    "clean": "rm -rf dist nodemodules",
    "clean:install": "npm run clean && npm install"
  }
}

Exécuter des scripts

# Scripts prédéfinis (pas besoin de "run")
npm start
npm test
npm stop
npm restart

# Autres scripts (nécessitent "run")
npm run build
npm run dev
npm run lint

# Passer des arguments
npm run test -- --watch
npm run build -- --mode production

# Exécuter plusieurs scripts
npm run lint && npm run test
npm run lint || npm run lint:fix

# Exécuter en parallèle (avec npm-run-all)
npm install -D npm-run-all
npm-run-all --parallel dev test:watch

# Scripts dans package.json
"scripts": {
  "start:all": "npm-run-all --parallel dev test:watch"
}

Hooks de lifecycle

{
  "scripts": {
    "prebuild": "npm run clean",
    "build": "tsc && vite build",
    "postbuild": "npm run test",

    "pretest": "npm run lint",
    "test": "vitest",
    "posttest": "echo 'Tests terminés!'",

    "preinstall": "node scripts/check-node-version.js",
    "postinstall": "husky install"
  }
}

6. npx : Exécuter des packages sans installation

Commandes courantes avec npx

# Créer un projet React
npx create-react-app mon-app
npx create-vite@latest mon-app -- --template react-ts

# Créer un projet Next.js
npx create-next-app@latest

# Lancer un serveur HTTP
npx http-server

# Vérifier les dépendances obsolètes
npx npm-check-updates

# Lancer un linter
npx eslint src

# Formatter du code
npx prettier --write src

# Générer des types TypeScript
npx tsc --init

# Benchmarking
npx autocannon http://localhost:3000

# Analyser le bundle
npx vite-bundle-visualizer

npx vs installation globale

# ❌ Installation globale (déconseillé)
npm install -g create-react-app
create-react-app mon-app

# ✅ Avec npx (recommandé)
npx create-react-app mon-app  # Toujours la dernière version

# Spécifier une version
npx create-react-app@5.0.0 mon-app

# Exécuter depuis un package local
npx -p cowsay cowsay "Hello!"

7. Workspaces et Monorepos

Structure d’un monorepo

mon-monorepo/
├── package.json
├── packages/
│   ├── app/
│   │   ├── package.json
│   │   └── src/
│   ├── ui-components/
│   │   ├── package.json
│   │   └── src/
│   └── utils/
│       ├── package.json
│       └── src/

Configuration NPM Workspaces

{
  "name": "mon-monorepo",
  "private": true,
  "workspaces": [
    "packages/"
  ],
  "scripts": {
    "build": "npm run build --workspaces",
    "test": "npm run test --workspaces",
    "dev": "npm run dev --workspace=packages/app"
  }
}

Configuration pnpm Workspaces

# pnpm-workspace.yaml
packages:
  - 'packages/'
  - 'apps/'
// packages/app/package.json
{
  "name": "@monorepo/app",
  "dependencies": {
    "@monorepo/ui-components": "workspace:",
    "@monorepo/utils": "workspace:"
  }
}

Commandes workspace

# Installer toutes les dépendances
npm install

# Installer dans un workspace spécifique
npm install react --workspace=packages/app

# Exécuter un script dans tous les workspaces
npm run build --workspaces

# Exécuter dans un workspace spécifique
npm run dev --workspace=packages/app

# Lister les workspaces
npm ls --workspaces

# Avec pnpm (plus efficace)
pnpm install
pnpm --filter @monorepo/app add react
pnpm --filter @monorepo/app run dev

8. Configuration .npmrc

Fichier .npmrc

# .npmrc à la racine du projet

# Registry (par défaut: registry.npmjs.org)
registry=https://registry.npmjs.org/

# Scope registry pour organisation
@monentreprise:registry=https://npm.pkg.github.com/

# Sauvegarder la version exacte (pas de ^)
save-exact=true

# Sauvegarder les deps dev avec -D par défaut
save-prefix=~

# Lockfile
package-lock=true

# Engine strict (force la version Node spécifiée)
engine-strict=true

# Pas d'installation de peer dependencies automatique
legacy-peer-deps=false

# Niveau de log
loglevel=warn

# Utiliser pnpm si disponible
prefer-workspace-packages=true

# Hoisting (pour monorepos)
shamefully-hoist=true

Configuration globale

# Voir la config
npm config list

# Définir une valeur
npm config set registry https://registry.npmjs.org/
npm config set init.author.name "Votre Nom"
npm config set init.license "MIT"

# Supprimer une valeur
npm config delete registry

# Config par défaut pour init
npm config set init-author-name "Votre Nom"
npm config set init-license "MIT"
npm config set init-version "0.0.1"

9. Sécurité et audit

Audit des vulnérabilités

# Analyser les vulnérabilités
npm audit

# Résultat détaillé
npm audit --json

# Corriger automatiquement
npm audit fix

# Corriger avec breaking changes
npm audit fix --force

# Avec pnpm
pnpm audit
pnpm audit --fix

Exemple de résultat d’audit

found 3 vulnerabilities (1 moderate, 2 high) in 1234 scanned packages
  run npm audit fix to fix 2 of them.
  1 vulnerability requires manual review.

Ignorer des vulnérabilités temporairement

// .npmrc
audit-level=high  // Ignorer les vulnérabilités low et moderate

Vérifier les licences

# Installer license-checker
npm install -g license-checker

# Lister toutes les licences
license-checker --summary

# Exporter en CSV
license-checker --csv --out licenses.csv

10. Optimisation et performance

Réduire la taille de nodemodules

# Avec pnpm (économise 50-70% d'espace)
npm install -g pnpm
pnpm install

# Nettoyer le cache NPM
npm cache clean --force

# Nettoyer les dépendances inutilisées
npm prune

# Analyser la taille des packages
npx package-size react react-dom

# Alternative: bundlephobia
npx cost-of-modules

Accélérer les installations

# Utiliser pnpm (3x plus rapide)
pnpm install

# Installer en parallèle (NPM 7+)
npm install --legacy-peer-deps

# Utiliser un cache local
npm config set cache ~/.npm-cache --global

# CI/CD: utiliser cache
  • uses: actions/cache@v3
  • with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('/package-lock.json') }}

Benchmarks (installation de React + Next.js)

Gestionnaire Temps Espace disque
npm 45s 350MB
yarn 32s 280MB
pnpm 18s 120MB
bun 12s 115MB

11. Publier un package NPM

Préparer le package

{
  "name": "@username/mon-package",
  "version": "1.0.0",
  "description": "Mon super package",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist",
    "README.md",
    "LICENSE"
  ],
  "scripts": {
    "build": "tsc",
    "prepublishOnly": "npm run build && npm test"
  },
  "keywords": ["react", "components"],
  "license": "MIT"
}

Publier

# Se connecter à NPM
npm login

# Vérifier qui est connecté
npm whoami

# Publier (première fois)
npm publish --access public

# Publier une nouvelle version
npm version patch  # 1.0.0 → 1.0.1
npm version minor  # 1.0.1 → 1.1.0
npm version major  # 1.1.0 → 2.0.0
npm publish

# Publier avec tag
npm publish --tag beta
npm install mon-package@beta

# Dépublier (< 72h)
npm unpublish mon-package@1.0.0

12. Exemple complet : Configuration moderne

// package.json
{
  "name": "modern-react-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "test": "vitest",
    "test:ui": "vitest --ui",
    "lint": "eslint src --ext ts,tsx",
    "lint:fix": "eslint src --ext ts,tsx --fix",
    "format": "prettier --write "src//.{ts,tsx,css}"",
    "type-check": "tsc --noEmit",
    "prepare": "husky install",
    "ci": "npm run type-check && npm run lint && npm run test"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.26.0"
  },
  "devDependencies": {
    "@types/react": "^18.3.5",
    "@types/react-dom": "^18.3.0",
    "@typescript-eslint/eslint-plugin": "^8.6.0",
    "@typescript-eslint/parser": "^8.6.0",
    "@vitejs/plugin-react": "^4.3.1",
    "@vitest/ui": "^2.0.5",
    "eslint": "^9.10.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-react": "^7.36.1",
    "eslint-plugin-react-hooks": "^4.6.2",
    "husky": "^9.1.5",
    "lint-staged": "^15.2.10",
    "prettier": "^3.3.3",
    "typescript": "^5.6.2",
    "vite": "^5.4.7",
    "vitest": "^2.0.5"
  },
  "engines": {
    "node": ">=20.0.0",
    "npm": ">=10.0.0"
  },
  "packageManager": "pnpm@9.12.0"
}
# .npmrc
save-exact=true
engine-strict=true
auto-install-peers=true
shamefully-hoist=true
# .github/workflows/ci.yml
name: CI

on: [push, pullrequest]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install --frozen-lockfile
      - run: pnpm run ci

Meilleures pratiques 2025

  • Utilisez pnpm pour les performances et l'espace disque
  • Committez les lockfiles pour la reproductibilité
  • Auditez régulièrement les vulnérabilités
  • Versions exactes pour les apps, ranges pour les libs
  • Scripts CI pour la validation automatique
  • Engines pour forcer les bonnes versions Node
  • Type: module pour ESM natif
  • Workspaces** pour les monorepos
  • Conclusion

    La maîtrise de NPM et de la gestion des dépendances est essentielle pour tout projet JavaScript moderne. Avec pnpm et les bonnes pratiques, vous aurez des installations rapides et fiables.

    Points clés

  • NPM/pnpm pour gérer les packages
  • package.json comme source de vérité
  • Lockfiles pour la reproductibilité
  • Scripts pour automatiser les tâches
  • Audit pour la sécurité
  • Ressources

  • NPM Documentation
  • pnpm Documentation
  • Node.js Best Practices
  • Une remarque, un retour ?

    Cet article est vivant — corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.