Leçon 3/5 9 min

Les ES Modules

export / import : découper son code JavaScript en fichiers réutilisables. Exports nommés et par défaut, et comment charger un module dans une page. La base du JS moderne.

FR EN

Le problème : un seul fichier géant

Au début, tout ton JS tient dans un fichier. Puis il grossit : 500, 2000 lignes… Tout est mélangé, les noms se télescopent, impossible de réutiliser une fonction ailleurs sans copier-coller. La solution moderne : découper en modules, des fichiers qui exportent ce qu'ils offrent et importent ce dont ils ont besoin.

export : offrir, import : prendre

Un module choisit ce qu'il rend public avec export. Un autre récupère ce qu'il veut avec import. Le reste du fichier reste privé au module.

// 📄 maths.js — exports NOMMÉS
export function tva(ht, taux = 0.20) {
  return ht * (1 + taux);
}
export const TAUX_REDUIT = 0.055;

function arrondi(n) { return Math.round(n * 100) / 100; }   // privé : pas exporté
// 📄 panier.js — on importe ce dont on a besoin
import { tva, TAUX_REDUIT } from "./maths.js";

console.log(tva(100));              // 120
console.log(tva(100, TAUX_REDUIT)); // 105.5

On importe par leur nom exact, entre accolades. On peut renommer à l'import avec as : import { tva as calculerTVA } from "./maths.js".

L'export par défaut

Un module peut avoir un export « principal », le default. À l'import, on lui donne le nom qu'on veut, sans accolades.

// 📄 Compte.js
export default class Compte {
  /* ... */
}
// 📄 app.js
import Compte from "./Compte.js";   // pas d'accolades, nom libre
const c = new Compte();

Convention courante : un export par défaut pour « la chose principale » du fichier (souvent une classe), et des exports nommés pour les utilitaires secondaires.

Charger un module dans une page

Pour qu'un navigateur traite un fichier comme un module (et comprenne import), on ajoute type="module" :

<script type="module" src="app.js"></script>

Un module est automatiquement en mode strict, et son code est différé (exécuté après le parsing du HTML, comme defer). Ses variables de premier niveau ne polluent pas le scope global : chaque module a son propre espace. C'est exactement l'encapsulation, mais à l'échelle du fichier.

Côté Node.js et outils (Vite, webpack…), c'est la même syntaxe import/export. Les bibliothèques npm s'importent pareil : import { useState } from "react". Apprendre les modules ici, c'est la clé d'entrée de tout l'écosystème moderne.

Rappel libre

Sans remonter dans la leçon : on a export function tva() {} et export default class Compte {} dans le même fichier. Comment importe-t-on les deux dans app.js ?

import Compte, { tva } from "./fichier.js" : le défaut prend n'importe quel nom et n'a pas d'accolades (il vient toujours en premier), le nommé garde son nom exact entre accolades.
Accepter ou rejeter le code de l'IA

L'IA propose ce module utilitaire. Ton rôle de relecteur : l'accepter tel quel ou le rejeter, et dire pourquoi.

// 📄 format.js
export default function euros(n) {
  return n.toFixed(2) + " €";
}
export default function pourcent(n) {
  return (n * 100).toFixed(1) + " %";
}
Rejeter : ce module ne se charge même pas. Un fichier ne peut avoir qu'un seul export default ; deux default lèvent une erreur de syntaxe (Duplicate export 'default') avant toute exécution. Ce ne sont d'ailleurs pas des exports « principaux » : ce sont deux utilitaires de même rang. Le bon réflexe : des exports nommés (export function euros / export function pourcent), importés avec import { euros, pourcent } from "./format.js".
Comment rend-on une fonction utilisable depuis un autre fichier ?
Différence entre export nommé et export par défaut ?
Prochaine étape

Code organisé, à toi les super-pouvoirs du navigateur : géolocalisation, notifications, presse-papiers, temps réel… Les Web APIs.

Leçon 4 : les Web APIs →

The problem: one giant file

At first, all your JS fits in one file. Then it grows: 500, 2000 lines… Everything is mixed, names collide, you can't reuse a function elsewhere without copy-paste. The modern solution: split into modules, files that export what they offer and import what they need.

export: offer, import: take

A module chooses what it makes public with export. Another grabs what it wants with import. The rest of the file stays private to the module.

// 📄 maths.js — NAMED exports
export function tva(ht, taux = 0.20) {
  return ht * (1 + taux);
}
export const TAUX_REDUIT = 0.055;

function arrondi(n) { return Math.round(n * 100) / 100; }   // private: not exported
// 📄 panier.js — import what you need
import { tva, TAUX_REDUIT } from "./maths.js";

console.log(tva(100));              // 120
console.log(tva(100, TAUX_REDUIT)); // 105.5

You import by their exact name, in braces. You can rename on import with as: import { tva as calculerTVA } from "./maths.js".

The default export

A module can have one "main" export, the default. On import, you give it any name you want, without braces.

// 📄 Compte.js
export default class Compte {
  /* ... */
}
// 📄 app.js
import Compte from "./Compte.js";   // no braces, free name
const c = new Compte();

Common convention: one default export for "the main thing" in the file (often a class), and named exports for secondary utilities.

Loading a module in a page

For a browser to treat a file as a module (and understand import), add type="module":

<script type="module" src="app.js"></script>

A module is automatically in strict mode, and its code is deferred (run after HTML parsing, like defer). Its top-level variables don't pollute the global scope: each module has its own space. That's exactly encapsulation, at the file scale.

In Node.js and tools (Vite, webpack…), it's the same import/export syntax. npm libraries are imported the same way: import { useState } from "react". Learning modules here is the entry key to the whole modern ecosystem.

Next step

Organized code — now the browser's superpowers: geolocation, notifications, clipboard, real time… The Web APIs.

Lesson 4: Web APIs →
Besoin d'un développeur pour votre projet ?

Réponse sous 24h · Sans engagement