Pendant longtemps, le langage JavaScript a souffert de l'absence d'un système de gestion de modules natif. Contrairement à Java ou Python, il était impossible de diviser naturellement une application complexe en plusieurs fichiers indépendants sans recourir à des bibliothèques tierces telles que RequireJS (AMD) ou SeaJS (CMD). L'arrivée de la norme ES6 a révolutionné cette approche en intégrant directement la modularité au cœur du langage.
Caractéristiques fondamentales des modules ES6
- Mode strict automatique : Tout code écrit dans un module s'exécute par défaut en mode strict (
"use strict"), même si la directive n'est pas explicitement déclarée. - Encapsulation de la portée : Chaque fichier constitue un module avec son propre contexte. Les variables, fonctoins ou classes déclarées à l'intérieur ne polluent pas l'espace global.
- Comportement Singleton : Un module n'est exécuté qu'une seule fois. Si plusieurs fichiers importent le même module, JavaScript utilise l'instance déjà présente en mémoire.
- Polyvalence : Il est possible d'exporter tout type de données : constantes, fonctions, objets, classes, etc.
L'exportation de données avec export
Pour rendre les éléments d'un module accessibles à d'autres fichiers, on utilise le mot-clé export. Il existe trois approches principales :
1. Exportations nommées individuelles
Cette méthode consiste à placer le mot-clé devant chaque déclaration.
export const apiKey = "AIzaSyB-890";
export function fetchData(url) {
console.log("Récupération des données depuis : " + url);
}
2. Exportation groupée (avec alias possible)
On peut églaement déclarer ses variables d'abord, puis les exporter en une seule fois à la fin du fichier. L'utilisation de as permet de renommer la sortie.
const serverPort = 3000;
const timeout = 5000;
const logger = (msg) => {
console.log(`[Log]: ${msg}`);
};
export { serverPort as port, logger };
3. Exportation par défaut
Chaque module ne peut avoir qu'un seul export par défaut. C'est pratique pour exporter une classe ou un objet de configuration principal.
const configuration = {
theme: "dark",
language: "fr"
};
export default configuration;
4. Exportations mixtes
Il est tout à fait possible de combiner un export par défaut et des exports nommés dans un même fichier.
export const version = "2.1.0";
export default function initApp() {
console.log("Application initialisée");
}
L'importation de modules avec import
Le mot-clé import permet de récupérer les fonctionnalités exposées par d'autres fcihiers.
1. Importation globale (Espace de noms)
Utilisez l'astérisque pour importer tout le contenu d'un module sous un seul objet.
<script type="module">
import * as Utils from './tools.js';
console.log(Utils.apiKey);
Utils.fetchData('/api/users');
</script>
2. Importation par décomposition (Destructuring)
Cette méthode permet de n'importer que les éléments nécessaires. Les alias sont aussi supportés ici avec as.
<script type="module">
import { port, logger } from './config.js';
import { version as appVer } from './core.js';
logger(`Démarrage sur le port ${port}`);
</script>
3. Importation simplifiée pour l'export par défaut
Pour un export par défaut, on peut choisir n'importe quel nom lors de l'importation sans utiliser d'accolades.
<script type="module">
import settings from './settings.js';
console.log(settings.theme);
</script>
4. Importations combinées
Si un fichier possède à la fois un export par défaut et des exports nommés, on peut les importer simultanément.
<script type="module">
import init, { version } from './app.js';
init();
console.log("Version logicielle :", version);
</script>