---
title: Les modules JavaScript
slug: Web/JavaScript/Guide/Modules
translation_of: Web/JavaScript/Guide/Modules
---
{{jsSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Métaprogrammation")}}
Ce guide aborde l'ensemble des notions vous permettant d'utiliser la syntaxe des modules en JavaScript.
## Un peu de contexte
Les programmes JavaScript ont commencé par être assez petits, réalisant des tâches isolées uniquement là où l'interactivité était nécessaire. Après plusieurs années, nous avons maintenant des applications complètes qui sont exécutées dans les navigateurs avec des codes complexes et volumineux. Des programmes JavaScript sont également exécutés dans d'autres contextes ([Node.js](/fr/docs/Glossary/Node.js) par exemple).
Il a donc été question de fournir un mécanisme pour diviser les programmes JavaScript en plusieurs modules qu'on pourrait importer les uns dans les autres. Cette fonctionnalité était présente dans Node.js depuis longtemps et plusieurs bibliothèques et _frameworks_ JavaScript ont permis l'utilisation de modules ([CommonJS](https://en.wikipedia.org/wiki/CommonJS), [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md), [RequireJS](https://requirejs.org/) ou, plus récemment, [Webpack](https://webpack.github.io/) et [Babel](https://babeljs.io/)).
Bonne nouvelle, les navigateurs ont également commencé à prendre en charge ces fonctionnalités nativement. C'est le sujet de ce guide.
Cette implémentation permettra aux navigateurs d'optimiser le chargement des modules, rendant le fonctionnement plus efficace qu'une bibliothèque tierce avec un traitement côté client des allers-retours sur le réseau.
## Compatibilité des navigateurs
L'utilisation des modules natifs JavaScript repose sur les instructions [`import`](/fr/docs/Web/JavaScript/Reference/Statements/import) et [`export`](/fr/docs/Web/JavaScript/Reference/Statements/export) dont vous pouvez voir l'état de la compatibilité ici :
### `import`
{{Compat("javascript.statements.import")}}
### `export`
{{Compat("javascript.statements.export")}}
## Commençons par un exemple
Pour illustrer le fonctionnement des modules, nous avons créé [un ensemble d'exemples disponibles sur GitHub](https://github.com/mdn/js-examples/tree/master/modules). Ces exemples illustrent un ensemble de modules pour créer un élément {{htmlelement("canvas")}} sur une page web puis dessiner (et afficher des informations) sur les différentes formes du canevas.
Ces opérations sont assez simples, mais nous les avons choisies pour nous concentrer plutôt sur le fonctionnement des modules.
> **Note :** Si vous souhaitez télécharger les exemples et les exécuter en local, vous devrez utiliser un serveur web local.
## Structure de l'exemple
Dans notre premier exemple (cf. [basic-modules](https://github.com/mdn/js-examples/tree/master/modules/basic-modules)), nous avons l'arborescence de fichier suivante :
```plain
index.html
main.js
modules/
canvas.js
square.js
```
> **Note :** Tous les exemples de ce guide suivent la même structure.
Le répertoire dédié aux modules contient deux modules :
- `canvas.js` — responsable de fonctions pour gérer le canevas
- `create()` — crée un canevas avec les dimensions souhaitées (`width` / `height`) à l'intérieur d'un élément {{htmlelement("div")}} doté d'un identifiant et qui est ajouté à l'intérieur d'un élément indiqué. Cette fonction renvoie l'objet contenant le contexte du canevas et l'identifiant du conteneur.
- `createReportList()` — crée une liste non ordonnée à l'intérieur d'un élément indiqué et dans lequel on affiche des données. Cette fonction renvoie l'identifiant de la liste.
- `square.js`
- `name` — une constante qui est une chaîne de caractères : `"square"`.
- `draw()` — dessine un carré avec une taille/position/couleur donnée sur le canevas indiqué. Cette fonction renvoie un objet contenant la taille du carré, sa position et sa couleur.
- `reportArea()` — écrit la surface d'un carré dans une liste donnée en fonction de la longueur de son côté.
- `reportPerimeter()` — écrit le périmètre d'un carré dans une liste donnée en fonction de la longueur de son côté.
## Aparté : `.mjs` ou `.js`
Tout au long de cet article, nous utiliserons l'extension `.js` pour les fichiers de nos modules. Toutefois, dans d'autres ressources, vous pourrez voir l'extension `.mjs` utilisée. Par exemple [dans les recommandations de la documentation de V8](https://v8.dev/features/modules#mjs). Les raisons alors fournies sont :
- Cela permet une meilleure clarté pour distinguer les fichiers qui sont des modules de ceux qui sont des fichiers JavaScript classiques.
- Cela permet que les fichiers de module soient analysés en tant que modules par les environnements d'exécution tels que [Node.js](https://nodejs.org/api/esm.html#esm_enabling), et les outils de compilation comme [Babel](https://babeljs.io/docs/en/options#sourcetype).
Toutefois, nous avons décidé de conserver l'extension `.js`. Pour que les modules fonctionnent dans les navigateurs, vous devez vous assurer qu'ils sont servis avec un en-tête `Content-Type` qui contient un type MIME JavaScript comme `text/javascript`. Si ce n'est pas le cas, vous aurez une erreur de vérification du type MIME et le navigateur n'exécutera pas le JavaScript de ces fichiers. La plupart des serveurs web utilisent le type MIME correct pour les fichiers `.js` mais pas encore pour les fichiers `.mjs`. Parmi les serveurs qui servent correctement les fichiers `.mjs`, on trouve [GitHub Pages](https://pages.github.com/) et [`http-server`](https://github.com/http-party/http-server#readme) en Node.js.
Il n'y a pas de problème si vous utilisez déjà un tel environnement ou si vous savez ce que vous faites et avez accès à la configuration de votre serveur pour paramétrer le bon [`Content-Type`](/fr/docs/Web/HTTP/Headers/Content-Type) pour les fichiers `.mjs`). Cela pourrait malheureusement être source de confusion si vous ne contrôlez pas le serveur qui sert les fichiers ou que vous publiez des fichiers pour un usage public (comme nous le faisons ici).
Aussi, à des fins d'apprentissage et de portabilité, nous avons décidé de conserver l'extension `.js` ici.
Si la distinction apportée par l'usage de `.mjs` pour identifier les modules (vs `.js` pour les fichiers JavaScript normaux) vous est utile, vous pouvez toujours utiliser l'extension `.mjs` pour le développement et convertir cette extension en `.js` lors de la compilation.
On notera que :
- Certains outils pourraient tout à fait ne jamais prendre en charge l'extension `.mjs`.
- Comme nous allons le voir plus bas, l'attribut `
```
On peut aussi embarquer directement le script du module dans le fichier HTML en plaçant le code JavaScript dans le corps de l'élément `
```
Le script dans lequel on importe les fonctionnalités du module agira comme le script de plus haut niveau. Si ce dernier est absent, Firefox (par exemple) lèvera une erreur SyntaxError: import declarations may only appear at top level of a module
.
Les instructions `import` et `export` ne peuvent être utilisées qu'à l'intérieur de modules et pas depuis des scripts classiques.
## Différences entre les modules et les scripts « classiques »
- Attention aux tests sur un environnement local : si vous chargez le fichier HTML directement depuis le système de fichier dans le navigateur (en double-cliquant dessus par exemple, ce qui donnera une URL `file://`), vous rencontrerez des erreurs CORS pour des raisons de sécurité. Il faut donc un serveur local afin de pouvoir tester.
- On pourra avoir un comportement différent entre un même script utilisé comme un module et un script utilisé de façon « classique ». En effet, les modules utilisent automatiquement [le mode strict](/fr/docs/Web/JavaScript/Reference/Strict_mode).
- Il n'est pas nécessaire d'utiliser l'attribut `defer` (voir [les attributs de `