1. CommonJS vs ES Modules
Node.js supporte deux systèmes de modules : CommonJS (CJS), le système historique, et ES Modules (ESM), le standard moderne du JavaScript. Comprendre leurs différences est essentiel pour choisir le bon système dans vos projets.
CommonJS (CJS) — Le système historique
// math-cjs.js — CommonJS
function additionner(a, b) { return a + b; }
const PI = 3.14159;
module.exports = { additionner, PI };
// Dans un autre fichier :
const { additionner, PI } = require('./math-cjs');
console.log(additionner(2, 3)); // 5
ES Modules (ESM) — Le standard moderne
// math-esm.mjs — ES Modules (extension .mjs)
// OU avec "type": "module" dans package.json → .js fonctionne aussi
export function additionner(a, b) { return a + b; }
export const PI = 3.14159;
export default function soustraire(a, b) { return a - b; }
// Dans un autre fichier :
import { additionner, PI } from './math-esm.mjs';
import soustraire from './math-esm.mjs';
console.log(additionner(2, 3)); // 5
// Top-level await possible avec ESM !
const data = await fetch('https://api.example.com/data').then(r => r.json());
Comparatif CJS vs ESM
| Critère | CommonJS (CJS) | ES Modules (ESM) |
|---|---|---|
| Import | require() | import |
| Export | module.exports | export / export default |
| Chargement | Synchrone | Asynchrone (statique) |
| Extension | .js (par défaut) | .mjs ou "type":"module" |
| Top-level await | Non | Oui |
| Tree-shaking | Non | Oui |
| Browser natif | Non | Oui |
| Usage Node.js | Projets existants, scripts | Nouveaux projets recommandé |
Activer ESM dans package.json
{
"name": "mon-projet",
"version": "1.0.0",
"type": "module"
}
// Avec "type": "module", tous les fichiers .js sont traités comme ESM
// Les fichiers .cjs restent CommonJS
2. Modules natifs essentiels
Node.js embarque de nombreux modules natifs. Pas besoin de npm pour ces fonctionnalités de base. Voici les plus importants à connaître.
fs — Système de fichiers
const fs = require('fs');
// Lire un fichier (synchrone pour les scripts)
const contenu = fs.readFileSync('config.json', 'utf8');
const config = JSON.parse(contenu);
// Écrire (asynchrone avec callback)
fs.writeFile('output.txt', 'Hello !', (err) => {
if (err) throw err;
console.log('Fichier écrit !');
});
path — Manipulation de chemins
const path = require('path');
// Joindre des segments de chemin (cross-platform !)
const fichier = path.join(__dirname, 'data', 'users.json');
// Windows : C:\projet\data\users.json
// Linux : /projet/data/users.json
console.log(path.basename('/home/user/photo.jpg')); // 'photo.jpg'
console.log(path.extname('index.html')); // '.html'
console.log(path.dirname('/home/user/photo.jpg')); // '/home/user'
console.log(path.resolve('config.json')); // Chemin absolu depuis CWD
os — Informations système
const os = require('os');
console.log('OS :', os.type()); // 'Linux', 'Windows_NT', 'Darwin'
console.log('Platform :', os.platform()); // 'linux', 'win32', 'darwin'
console.log('Hostname :', os.hostname()); // Nom de la machine
console.log('CPU(s) :', os.cpus().length); // Nombre de coeurs
console.log('RAM totale :', (os.totalmem() / 1073741824).toFixed(1) + ' Go');
console.log('RAM libre :', (os.freemem() / 1073741824).toFixed(1) + ' Go');
console.log('Dossier home :', os.homedir()); // /home/user ou C:\Users\user
crypto — Hachage et sécurité
const crypto = require('crypto');
// Hash SHA-256
const hash = crypto.createHash('sha256')
.update('mon texte secret')
.digest('hex');
console.log('SHA-256 :', hash);
// UUID aléatoire (Node.js >= 14.17)
const uuid = crypto.randomUUID();
console.log('UUID :', uuid); // ex: '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
// Octets aléatoires (pour tokens)
const token = crypto.randomBytes(32).toString('hex');
console.log('Token :', token);
events — EventEmitter
const EventEmitter = require('events');
// Créer un émetteur personnalisé
class MonEmetteur extends EventEmitter {}
const emetteur = new MonEmetteur();
// Écouter des événements
emetteur.on('data', (payload) => {
console.log('Données reçues :', payload);
});
emetteur.once('connect', () => {
console.log('Connecté ! (une seule fois)');
});
// Émettre des événements
emetteur.emit('connect');
emetteur.emit('data', { user: 'Alice', timestamp: Date.now() });
emetteur.emit('data', { user: 'Bob', timestamp: Date.now() });
3. npm — Gestion des packages
npm est le gestionnaire de packages officiel de Node.js avec plus de 2 millions de packages. Voici les commandes essentielles à maîtriser.
Installer et désinstaller
# Installer une dépendance de production
npm install express
npm i express # Raccourci
# Installer plusieurs packages
npm install express dotenv cors
# Dépendance de développement uniquement
npm install --save-dev nodemon
npm i -D nodemon # Raccourci
# Installer une version précise
npm install express@4.18.2
# Désinstaller
npm uninstall express
npm un express # Raccourci
Lister et mettre à jour
# Lister les packages installés
npm list
npm list --depth=0 # Sans les sous-dépendances
# Voir les packages obsolètes
npm outdated
# Mettre à jour
npm update # Selon les ranges semver
npm update express # Package spécifique
# Voir les infos d'un package
npm info dayjs
npm info dayjs version # Dernière version seulement
Sécurité et audit
# Vérifier les vulnérabilités
npm audit
# Corriger automatiquement
npm audit fix
npm audit fix --force # ⚠️ Peut casser des APIs
npx — Exécuter sans installer
# Exécuter un package sans l'installer globalement
npx create-react-app mon-app
npx eslint src/
npx prettier --write src/
# Exécuter une version spécifique
npx node@18 --version
# Liste des packages globaux installés
npm list -g --depth=0
Exemple : utiliser dayjs
// Après : npm install dayjs
const dayjs = require('dayjs');
require('dayjs/locale/fr');
dayjs.locale('fr');
const maintenant = dayjs();
console.log(maintenant.format('dddd D MMMM YYYY')); // vendredi 15 novembre 2024
console.log(maintenant.add(7, 'day').format('DD/MM/YYYY')); // Dans 7 jours
console.log(dayjs('2024-01-01').fromNow()); // Il y a X mois
4. package.json en détail
Le fichier package.json est le manifeste de votre projet Node.js.
Il décrit le projet, ses dépendances et ses scripts.
Champs principaux
{
"name": "mon-api-node", // Identifiant unique (lowercase, tirets)
"version": "1.2.3", // SemVer obligatoire
"description": "API REST Node", // Description courte
"main": "src/index.js", // Point d'entrée du module
"type": "module", // "module" pour ESM, omis pour CJS
"scripts": {
"start": "node src/index.js", // npm start
"dev": "nodemon src/index.js", // npm run dev
"test": "node tests/run.js", // npm test
"lint": "eslint src/", // npm run lint
"build": "node scripts/build.js" // npm run build
},
"dependencies": {
"express": "^4.18.2", // Prod : nécessaire au runtime
"dotenv": "^16.3.1"
},
"devDependencies": {
"nodemon": "^3.0.2", // Dev : uniquement en développement
"eslint": "^8.56.0"
},
"engines": {
"node": ">=18.0.0", // Version Node.js minimale requise
"npm": ">=9.0.0"
},
"private": true, // Empêche la publication sur npm
"license": "MIT",
"author": "Alaa EL HUSSEIN "
}
dependencies vs devDependencies
| Type | Quand utiliser | Exemple | Installé en prod ? |
|---|---|---|---|
dependencies | Nécessaire au runtime | express, dotenv, mongoose | Oui |
devDependencies | Build, tests, outils dev | nodemon, eslint, jest | Non (avec --production) |
npm install --production ou NODE_ENV=production npm install
pour n'installer que les dependencies et économiser de l'espace.
5. Semantic Versioning (SemVer)
Le versionnage sémantique définit comment les numéros de version communiquent l'impact des changements. Comprendre SemVer est indispensable pour gérer les dépendances de façon sûre.
Structure d'une version
1 . 2 . 3
↑ ↑ ↑
MAJEURE MINEURE PATCH
MAJEURE : Changement incompatible (breaking change)
MINEURE : Nouvelle fonctionnalité, rétrocompatible
PATCH : Correction de bug, rétrocompatible
Opérateurs de range
| Notation | Range acceptée | Exemple concret | Utilisation |
|---|---|---|---|
1.2.3 | Exactement 1.2.3 | Uniquement 1.2.3 | Reproductibilité totale |
^1.2.3 | >=1.2.3 <2.0.0 | 1.2.3 à 1.x.x | Par défaut npm — sûr |
~1.2.3 | >=1.2.3 <1.3.0 | 1.2.3 à 1.2.x | Conservateur |
* | Toute version | Dernière stable | ⚠️ Risqué |
>=1.0.0 | 1.0.0 et plus | Toutes >= 1.0.0 | Rare |
1.2.x | >=1.2.0 <1.3.0 | Équivalent à ~1.2.0 | Explicit |
package-lock.json — Verrouillage des versions
# package.json dit : "express": "^4.18.2"
# → npm peut installer 4.19.0, 4.20.1, etc.
# package-lock.json dit : express@4.18.2 exactement
# → npm install réinstalle EXACTEMENT la même version
# Toujours committer package-lock.json !
# Ne pas modifier package-lock.json manuellement.
# Régénérer le lock (après conflit git par ex.) :
rm package-lock.json
npm install
Versions pre-release et tags
# Installer une version pre-release
npm install express@next
npm install react@canary
# Publier avec un tag (pour les auteurs de packages)
npm publish --tag beta # Version beta
npm publish --tag latest # Production (défaut)
npm install, vérifiez ce qui a changé
avec npm outdated. Mettez à jour régulièrement et testez après chaque mise à jour majeure.