DEV Community

Cover image for Le package.json
Benjamin Auzanneau
Benjamin Auzanneau

Posted on • Edited on • Originally published at 616.earth

Le package.json

Le manifeste

Le package.json est le fichier manifeste d'un projet JavaScript. Il raconte ce que ton projet est, ce dont il dépend et comment il se construit ou se lance.

L'origine

Au debut de Node.js, chaque module devait declarer son nom, sa version et ses dépendances pour etre installé correctement. Le package.json s'est imposé avec npm comme format standard pour decrire un package.

C'etait un moyen simple et lisible de partager un module et de permettre a npm de résoudre les dépendances.

Il n'y a pas que npm qui utilise le package.json : yarn, pnpm et d'autres gestionnaires de paquets s'appuient aussi dessus avec une façon différente de gérer les dépendances et surtout, le moyen de les résoudre.

Les attributs

Dans les grandes lignes, on trouve plusieurs categories de champs dans le package.json :

Catégorie Description
Identité name, version, description, license, author
Dépendances dependencies, devDependencies, peerDependencies, optionalDependencies
Scripts commandes standardisées (npm run dev, build, test, etc.) ou non
Compatibilité engines, os, cpu pour cadrer l'environnement
Publication ce qui est inclus dans le package, la version, les fichiers d'entrée
Customisation des champs spécifiques aux outils (babel, eslint, jest, etc.) ou tout simplement que vous souhaitez utiliser

Dans la partie scripts, j'ai récemmenet découvert un mécanisme sympa : pre<nomScript> et post<nomScript> se lancent automatiquement avant/après n'importe quel script (ex: prebuild / postbuild autour de build).

{
  "name": "mon-projet", // identite du package
  "version": "1.0.0", // version publiee
  "description": "Mon app de demo",
  "license": "MIT", // license du package
  "author": "necraidan",
  "scripts": {
    "dev": "vite", // commande de dev
    "build": "vite build", // build de production
    "test": "vitest" // tests
  },
  "dependencies": {
    "react": "^18.3.0" // deps runtime
  },
  "devDependencies": {
    "vite": "^5.4.0", // outils de dev
    "vitest": "^2.1.0"
  },
  "peerDependencies": {
    "react": ">=18" // compatibilité attendue
  },
  "optionalDependencies": {
    "fsevents": "^2.3.3" // optionnel (ex: macOS)
  },
  "engines": {
    "node": ">=20" // version node ciblee
  },
  "eslintConfig": {
    "extends": ["eslint:recommended"] // champs custom
  }
}
Enter fullscreen mode Exit fullscreen mode

Les types de dépendances

Type Description
dependencies indispensables au fonctionnement de l'app en production
devDependencies utiles en développement (tests, lint, build), pas nécessaires en prod
peerDependencies indiquent la compatibilité attendue avec un autre package sans l'embarquer soi‑même (ex. une lib React qui attend React installé)
optionalDependencies optionnelles ; si l'installation échoue, npm continue quand même. À toi de gérer l'absence au runtime
bundleDependencies dépendances embarquées lors de la publication du package

Pour aller plus loin, la documentation officielle du package.json.

Focus sur les peerDependencies

Une peerDependency, c'est une dépendance que ton package n'installe pas lui-même : il déclare seulement une compatibilité.

le but : éviter les doublons et les conflits de versions (cas typiques : eslint, vite, react côté librairies).

Depuis npm 7+, les peers sont prises en compte automatiquement pendant la résolution et des conflits de versions peuvent faire échouer l'installation :

{
  "name": "eslint-plugin-acme",
  "peerDependencies": {
    "eslint": "^9.0.0"
  },
  "peerDependenciesMeta": {
    "typescript": {
      "optional": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Ici, le plugin n'installe pas eslint : il annonce juste la version attendue. C'est le projet hôte qui doit fournir eslint (en dependencies ou devDependencies selon son usage).

Le bloc peerDependenciesMeta indique que typescript est une peer optionnelle : si typescript n'est pas présent dans le projet hôte, l'installation ne doit pas échouer pour cette raison.

Le lockfile de npm : le package-lock.json

Un lockfile permet de fixer des dépendances. Il est conçu pour être versionné dans votre repo afin de pouvoir avoir une rejouabilité des installations prédictibles. Cependant, cela peut varier selon l’OS ou l'architecture, les dépendances optionnelles ou les champs encore les ce qui est spécifié dans les champs os/cpu.

Le package-lock.json décrit l’état exact résolu : l’arbre complet des dépendances (y compris transitives), avec versions précises, sources de téléchargement (resolved) et empreintes (integrity).

Ce qu’on trouve dedans

Concrètement, on va y trouver un lockfileVersion pour la version du format. La partie packages est la description des packages par chemin, avec resolved et integrity (présent avec le package-lock.json v2+, npm 7+ ; aujourd'hui, npm 9+ génère un lockfileVersion: 3).

npm install vs npm ci

La commande npm install va installer les dépendances en s’appuyant sur package.json et le package-lock.json. Il peut le régénérer ou le modifier selon les cas.

La commande npm ci va suivre le package-lock.json, elle échoue si le package.json et le package-lock.json ne correspondent pas, supprime les node_modules (en théorie 😅) avant de lancer l'installation et ne touche pas au package-lock.json.

Cas avancés

npm-shrinkwrap.json a priorité sur package-lock.json et fige l'arbre des dépendances pour un package publié. En pratique, c'est surtout adapté aux applications/CLI publiées, et généralement déconseillé pour les bibliothèques.

L'attribut overrides peut être utiliser pour de forcer une version d’une dépendance transitive pour surcharger une version particulière.

Conclusion

Le package.json décrit l’intention de ton projet (scripts, compatibilité, plages de versions). Le package-lock.json, lui, fige l’état exact installé : c’est ce qui rend les builds reproductibles. En pratique : on versionne le lockfile, on installe avec npm ci en CI, et on relit ses diffs comme du code. C’est ce duo qui évite les “ça marche chez moi” et stabilise le projet dans le temps.

Encore une fois c'est un mémo sans doute trivial en partie mais qui permet de réunir en un seul endroit l'essentiel de ce qu'est le package.json.


Sources

Top comments (0)