Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

Export par défaut, exports nommés et import dynamique

Export par défaut, exports nommés et import dynamique. Dans cette leçon du cours JavaScript, vous apprendrez à : utiliser un export par défaut et des exports nommés dans le même module ; renommer un i...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Export par défaut, exports nommés et import dynamique. Dans cette leçon du cours JavaScript, vous apprendrez à : utiliser un export par défaut et des exports nommés dans le même module ; renommer un import avec as et regrouper les imports avec import * as ; créer un fichier « baril » qui ré-exporte plusieurs modules ; comprendre les liaisons vivantes et charger un module à la demande avec import().

Chapitre 17 — Les modules et l'organisation du code · 17.2 Export par défaut, exports nommés et import dynamique

🎯 Objectifs de la leçon
• utiliser un export par défaut et des exports nommés dans le même module ;
• renommer un import avec as et regrouper les imports avec import * as;
• créer un fichier « baril » qui ré-exporte plusieurs modules ;
• comprendre les liaisons vivantes et charger un module à la demande avec import().

Tableau des formes d'export et d'import
Figure 1 — Les cinq façons de partager du code entre modules.

1. Export par défaut et exports nommés

  • Export nommé: autant qu'on veut par fichier ; on les importe entre accolades, avec leur nom exact.
  • Export par défaut (export default) : un seul par fichier, pour la « chose principale » du module (une classe, un composant…). On l'importe sans accolades, avec le nom de son choix.

📄 utilisateur.js

// Export PAR DÉFAUT : la « chose principale » du module (un seul par fichier)
export default class Utilisateur {
  constructor(nom, role = "membre") {
    this.nom = nom;
    this.role = role;
  }
  presenter() {
    return `${this.nom} (${this.role})`;
  }
}

// Exports NOMMÉS : des éléments secondaires (autant qu'on veut)
export const ROLES = ["membre", "admin"];
export function estAdmin(utilisateur) {
  return utilisateur.role === "admin";
}

📄 outils/texte.js

export const majuscules = (t) => t.toUpperCase();
export const inverser = (t) => [...t].reverse().join("");

📄 outils/nombres.js

export const moyenne = (liste) => liste.reduce((s, x) => s + x, 0) / liste.length;

📄 outils/index.js

// « Fichier baril » : il ré-exporte, pour offrir un seul point d'entrée
export { majuscules, inverser } from "./texte.js";
export { moyenne } from "./nombres.js";

📄 main.js

// Défaut : nom libre, sans accolades. Nommés : entre accolades, nom exact.
import Personne, { ROLES, estAdmin as verifierAdmin } from "./utilisateur.js";
import * as Outils from "./outils/index.js";

const amina = new Personne("Amina", "admin");
console.log(amina.presenter());
console.log("Rôles :", ROLES.join(", "));
console.log("Admin ?", verifierAdmin(amina));

// Espace de noms : tous les exports sous un seul objet
console.log(Outils.majuscules("modules"), Outils.inverser("abc"));

Dans le terminal : node main.js

Amina (admin)
Rôles : membre, admin
Admin ? true
MODULES cba
  • import Personne, { … }: le défaut (Personne, nom choisi librement) puis les nommés.
  • estAdmin as verifierAdmin: renomme un import, utile en cas de conflit de noms.
  • import * as Outils: tous les exports nommés regroupés dans un objet.
  • outils/index.js est un fichier baril: il ne contient rien d'autre que des ré-exports et offre un point d'entrée unique pour le dossier.
ℹ️ À retenir
Beaucoup d'équipes préfèrent n'utiliser que des exports nommés: le nom est le même partout, l'éditeur peut renommer automatiquement et l'auto-complétion fonctionne mieux. L'export par défaut reste courant pour une classe ou un composant unique par fichier.

2. Les imports sont des liaisons vivantes

Un import n'est pas une copie de la valeur : c'est une vue en lecture seule sur la variable du module d'origine.

📄 compteur.js

// Les imports sont des LIAISONS VIVANTES (live bindings), pas des copies
export let total = 0;
export function incrementer() {
  total++;
}

📄 live.js

import { total, incrementer } from "./compteur.js";

console.log("Avant :", total);
incrementer();
incrementer();
console.log("Après :", total); // la valeur importée a suivi

try {
  total = 100; // interdit : un import est en lecture seule
} catch (e) {
  console.log(e.constructor.name + " :", e.message);
}

Dans le terminal : node live.js

Avant : 0
Après : 2
TypeError : Assignment to constant variable.

Le module qui importe voit les changements, mais ne peut pas réassigner la variable. Seul le module propriétaire peut la modifier, ici par la fonction incrementer.

3. L'import dynamique : import()

Les instructions import … from sont statiques: elles s'écrivent en haut du fichier, et tous les modules sont chargés au démarrage. import("chemin"), avec des parenthèses, est une fonction qui charge un module au moment où elle s'exécute et renvoie une promesse (voir le chapitre 18).

📄 export-csv.js

console.log("(module export-csv chargé)");
export function versCSV(lignes) {
  return lignes.map((l) => l.join(";")).join("\n");
}

📄 dynamique.js

// import() dynamique : charge un module SEULEMENT quand on en a besoin
const notes = [["Amina", 15], ["Sami", 12]];

async function exporter(format) {
  if (format === "csv") {
    const { versCSV } = await import("./export-csv.js"); // renvoie une promesse
    return versCSV(notes);
  }
  return JSON.stringify(notes);
}

console.log("Démarrage : export-csv.js n'est pas encore chargé");
console.log(await exporter("json"));
console.log(await exporter("csv"));
console.log(await exporter("csv")); // 2e appel : module déjà en cache, pas rechargé

Dans le terminal : node dynamique.js

Démarrage : export-csv.js n'est pas encore chargé
[["Amina",15],["Sami",12]]
(module export-csv chargé)
Amina;15
Sami;12
Amina;15
Sami;12

Le message « module export-csv chargé » n'apparaît qu'au premier export CSV, et une seule fois : un module n'est évalué qu'une fois, puis mis en cache. await est autorisé directement dans dynamique.js parce que c'est un module (top-level await).

Quand l'utiliser ? Pour une fonctionnalité lourde et rarement utilisée (export PDF, éditeur de texte riche, graphique), pour charger une langue selon l'utilisateur, ou un module différent selon l'appareil.

ℹ️ À retenir
• Nommés : export const x → import { x }; défaut : export default → import nomLibre.
• as renomme ; import * as M regroupe ; export { x } from ré-exporte.
• Un import est une liaison vivante en lecture seule.
• import() charge un module à la demande et renvoie une promesse ; un module n'est évalué qu'une fois.

🛠 Activité 2 — Une petite bibliothèque d'outils

Mission : Créez un dossier outils/ contenant texte.js, dates.js et index.js, ainsi qu'une classe Etudiant en export par défaut.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Dans texte.js, écrivez capitaliser, compterMots et slug (« Bonjour le monde » → « bonjour-le-monde »). Export nommé ou par défaut ? Pourquoi ?
  2. Créez etudiant.js qui exporte par défaut une classe Etudiant et, en exports nommés, une constante NIVEAUX. Écrivez l'import qui récupère les deux en une seule ligne.
  3. Importez la classe sous le nom Eleve. Est-ce possible ? Et pour un export nommé, que faut-il écrire ?
  4. Écrivez outils/index.js pour qu'un fichier puisse faire import { capitaliser, formaterDate } from "./outils/index.js". Quel est l'intérêt si vous déplacez plus tard capitaliser dans un autre fichier ?
  5. Reproduisez l'exemple du compteur avec un module score.js. Pourquoi l'auteur du module a-t-il intérêt à ce que les autres ne puissent pas modifier score directement ?
  6. Ajoutez une fonction exporterPDF dans un module séparé, chargé avec import() seulement si l'utilisateur tape « pdf ». Ajoutez un console.log en haut du module : combien de fois s'affiche-t-il si on exporte trois fois ?
  7. Que renvoie import("./inexistant.js")? Comment gérez-vous l'erreur ?

Je vérifie / je rends :

  • ☐ Le dossier complet et un main.js qui démontre chaque forme d'import.
  • ☐ Les réponses aux questions 3, 5 et 6.

← 17.1 Les fichiers et modules JavaScript (import / export)17.3 Les modules dans le navigateur et dans Node.js →