À propos de ce cours
Chapitre 17 — Les modules et l'organisation du code · 17.3 Les modules dans le navigateur et dans Node.js
Nouvelle leçon : avant d'organiser un projet, il faut savoir faire fonctionner les modules là où le code s'exécute. C'est la source d'erreurs la plus fréquente chez les débutants (page blanche, erreur CORS, « Cannot use import statement outside a module »).
• charger un module dans une page avec
<script type="module">; • connaître les différences entre un script classique et un module ;
• lancer un serveur local et comprendre l'erreur CORS en
file://; • configurer Node.js pour les modules ES et reconnaître l'ancien système CommonJS.

Figure 1 — Deux environnements, deux configurations.
1. Dans le navigateur : type="module"
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Mon application</title>
<!-- Une seule balise : le point d'entrée. Le navigateur charge lui-même les imports. -->
<script type="module" src="src/main.js"></script>
</head>
<body>
<h1>Bonjour</h1>
</body>
</html>
Script classique <script src> | Module <script type="module"> | |
|---|---|---|
| Portée | globale, partagée | propre au fichier |
import / export | interdits (erreur de syntaxe) | autorisés |
| Moment d'exécution | immédiat, bloque l'affichage | différé (comme defer) : après la lecture du HTML |
| Mode strict | non, sauf "use strict" | toujours |
this au niveau du fichier | window | undefined |
| Chargé plusieurs fois | exécuté à chaque balise | exécuté une seule fois |
Ouvert en file:// | fonctionne | bloqué (CORS) |
2. L'erreur CORS et le serveur local
Si vous ouvrez la page en double-cliquant sur index.html, l'adresse commence par file:/// et la console affiche :
Access to script at 'file:///…/src/main.js' from origin 'null' has been blocked by CORS policy:
Cross origin requests are only supported for protocol schemes: … http, https.
Pour des raisons de sécurité, les navigateurs ne chargent les modules que par HTTP. Il faut donc un serveur local:
- VS Code: extension Live Server, puis clic droit sur
index.html› Open with Live Server; - Node.js:
npx serve .dans le dossier du projet ; - Python:
python -m http.server 8000, puis ouvrirhttp://localhost:8000.
3. Un module n'est exécuté qu'une fois
Même importé par plusieurs fichiers, un module est évalué une seule fois. Tous les importateurs partagent les mêmes objets :
📄 config.js
console.log("→ config.js est évalué");
export const config = { langue: "fr", theme: "clair" };
📄 a.js
import { config } from "./config.js";
export function changerTheme() {
config.theme = "sombre";
}
📄 main.js
import { config } from "./config.js";
import { changerTheme } from "./a.js"; // a.js importe AUSSI config.js
import { config as encore } from "./config.js";
changerTheme();
console.log("Thème vu par main.js :", config.theme);
console.log("Même objet ?", config === encore);
console.log("this au niveau du module :", this);
Dans le terminal : node main.js
→ config.js est évalué Thème vu par main.js : sombre Même objet ? true this au niveau du module : undefined
C'est pratique pour partager une configuration ou un état. C'est aussi un risque : un module peut modifier un objet utilisé par tous les autres.
4. Dans Node.js : modules ES et CommonJS
Node.js existait avant les modules ES. Il a son propre système, CommonJS (require / module.exports),
encore très présent dans les anciens projets et dans les tutoriels. Node.js choisit le système ainsi :
- fichier
.mjs→ module ES ; fichier.cjs→ CommonJS ; - fichier
.js→ module ES si lepackage.jsonle plus proche contient"type": "module", sinon CommonJS.
📄 package.json
{ "type": "commonjs" }
📄 salutation.js
// Ancien système de Node.js : CommonJS
function saluer(nom) {
return `Bonjour ${nom}`;
}
module.exports = { saluer };
📄 main.js
const { saluer } = require("./salutation"); // require : synchrone, extension facultative
console.log(saluer("Lina"));
Dans le terminal : node main.js
Bonjour Lina
Le message « Cannot use import statement outside a module » signifie que Node.js (ou le navigateur) traite votre fichier comme un script classique ou CommonJS : ajoutez
"type": "module" au package.json, utilisez l'extension .mjs, ou type="module" dans la balise <script>. • Navigateur :
<script type="module" src="…"> sur le seul point d'entrée.• Un module est différé, en mode strict, avec sa propre portée, et n'est exécuté qu'une fois.
• Les modules exigent HTTP : utilisez un serveur local, jamais
file://. • Node.js :
"type": "module" ou .mjs pour les modules ES ; require = CommonJS (ancien).🛠 Activité 3 — Faire tourner des modules partout
Mission : Reprenez le convertisseur de l'activité 1 et faites-le fonctionner dans une page web, puis dans Node.js sans package.json.
Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :
- Créez
index.htmlavec un champ et un bouton qui affiche la conversion. Ouvrez-la en double-cliquant : que voyez-vous dans la page ? Dans la console (F12) ? - Lancez un serveur local avec l'une des trois méthodes. Quelle adresse ouvrez-vous ? L'application fonctionne-t-elle maintenant ?
- Ajoutez
console.log(this)en haut demain.js, puis enleveztype="module"de la balise. Qu'affiche la console dans chaque cas ? Quelle autre erreur apparaît sanstype="module"? - Placez la balise
<script type="module">dans le<head>et utilisezdocument.querySelector("#bouton")dès la première ligne. Cela fonctionne-t-il ? Et avec un script classique au même endroit ? Expliquez avec le mot « différé ». - Sans
package.json, renommez vos fichiers pour que Node.js les traite comme des modules ES. Quels changements faut-il aussi faire dans les chemins d'import ? - Ouvrez un projet Node.js existant sur GitHub (par exemple un projet Express ancien). Utilise-t-il
requireouimport? Comment le savez-vous rapidement ?
Je vérifie / je rends :
- ☐ La page web du convertisseur fonctionnant avec un serveur local (capture avec la barre d'adresse visible).
- ☐ Le tableau de vos observations pour les questions 3 et 4.
← 17.2 Export par défaut, exports nommés et import dynamique17.4 Organiser un projet JavaScript en modules →