Contenu
- 1 Qu’est ce qu’un module en Javascript?
- 2 Et vinrent les modules Javascript
- 3 Les caractéristiques de modules
- 3.1 Les modules utilisent le mode strict
- 3.2 Le scope des variables
- 3.3 Evaluation une seule fois du module à l’import
- 3.4 La propriété meta de import
- 3.5 Le mot clé this dans un module
- 3.6 Les script module sont deferred dans un client
- 3.7 Toujours préciser le chemin,
- 3.8 scripts externes et CORS
- 3.9 async et les modules
Qu’est ce qu’un module en Javascript?
Un module est un fichier tout simplement rien de plus. On parle de module en javascript moderne, en effet ce concept n’existait pas avant ES6. Les modules existent en NodeJs également. Mais dans cet article je ne vais parler que des modules côté client.
Avant l’existence des modules, on ne pouvait pas importer un fichier Javascript dans un autre fichier Javascript comme on peut le faire en PHP.
Ici on ne va parler que des modules front end, dont la syntaxe est différente des modules dans NodeJS, dans ce dernier il existe au moins deux façon de faire, avec require() (commonJs) et import (AMD).
Comment on faisait avant pour importer un script Javascript?
#index.html <html> ... <body> .. <script src="index.js"></script> <script src="helper.js"></script> ...
On se servait de la balise script our importer les fichiers, index.js ne pouvait pas importer helper.js. La conséquence est que dans un fichier HTML on pouvait avoir facilement plus d’une dizaine d’import de fichier javascript. Cela pouvait avoir un impoact sur la rapidité du site.
Et vinrent les modules Javascript
Dès qu’il y a un import de modules, on observe au minimum deux fichiers. Soient deux fichiers, un principal.js, et un helper.js
//index.html <script type="module"> import {sayHi} from './helper.js'; sayHi('John'); </script> // helper.js export function sayHi(name){ console.log('Hello ' + name) }
On peut importer une fonction à condition qu’elle ait été exportée depuis le fichier helper.js. Dans la balise script on doit ajouter l’attribut type= »module » pour que cela marche.
Les caractéristiques de modules
Les modules utilisent le mode strict
Dans un code Javascript vous utilisez le mode strict pour forcer une plus grande rigueur dans la programmation Par exemple dans un fichier HTML <script> a = 5 // autorisé pas d'erreur dans la console </script> Par contre <script> "use strict" a = 5 // ReferenceError: a is not defined </script> de même dans un module <script type="module"> a = 5 // ReferenceError: a is not defined bien qu'on n'ait pas eu à mettre use strict </script>
Le scope des variables
Chaque module a son scope pour ses variables (je parle des variable globales du module, pas les variable locales des fonctions), les modules ne communiquenet donc pas leur variables, autrement dit, un module ne peut utiliser une variable globales d’un autre module.
// user.js let user = "Jules" // main.js console.log(user) // //index.html <script type="module" src="user.js"></script> <script type="module" src="hello.js"></script> la console va afficher "SyntaxError: The requested module './lib.js' does not provide an export named 'user'" //on modifie dans user.js export let user = "Jules" // correct //Pour illustrer directement dans une page HTML <script type="module"> export let user = "Jules" </script> <script type="module"> console.log(user) // Erreur,et on ne peut faire import du module puisqu'il est inline, la seule façon urait été de faire window.user = "Jules" </script>
Evaluation une seule fois du module à l’import
//index.html <script type="module"> window.test = 0 </script> <script type="module"> import { val } from './util.js' </script> <script type="module"> import { val } from './util.js' console.log(val) </script> // util.js window.test++ export let val = window.test
bien que l’on ait importé deux fois le module util.js, le code va afficher 1 et non 2
Prenons un autre exemple, qui va montrer que cet aspect est en fait pratique, permet aux différents scripts de se « partager » une variable
// config.js export let config = {}; // 1.js import { config } from './config.js' config.user = "user1" //2.js import { config } from './config.js' config.url = "http://local.test/user1" // index.html <script type="module" src="1.js"></script> <script type="module" src="2.js"></script> <script type="module"> import { config } from './config.js' console.log(config) </script>
L’exemple ci-dessus montre que les fichier 1.js et 2.js apportent des nouvelles propriétés
La propriété meta de import
// en reprenant l'exemple précédent // index.html <script type="module" src="1.js"></script> <script type="module" src="2.js"></script> <script type="module"> import { config } from './config.js' console.log(import.meta) </script>
On obtient quelques informations sur le module courant.
Le mot clé this dans un module
Dans un module le mot clé this n’existe pas, il est undefined
<script> alert(this); // window </script> <script type="module"> alert(this); // undefined </script>
Les script module sont deferred dans un client
Ce qui suit n’est valable que dans un navigateur
Vous connaissez l’attribut defer dans la balise script.
<script type="module"> alert(typeof button); // ce module est defer, il se télécharge immédiatement, mais il attend que le HTML finisse de se télécharger avant de s'exécuter. </script> <script> alert(typeof button); // s'exécute immédiatement après le téléchargement, avant que le HTML du bouton ne vienne </script> <button id="button">Button</button>
Toujours préciser le chemin,
Même si le script est adjacent à votre page HTML, il faut préfixer avec un point slash
import {compteur} from 'util.js'; // dans un navigateur ceci n'est pas autorisé,TypeError: Failed to resolve module specifier "util.js". Relative references must start with either "/", "./", or "../". import {compteur} from './util.js';
scripts externes et CORS
L’inclusion de script externe en tant que module doit se faire avec précaution dans le cas des modules. Pour les scripts externes de même origine que la page HTML, pas de soucis, mais si le script vient d’un autre nom de domaine, alors le serveur d’origine
<script type="module" src="https://site.com/script.js"></script> il faut que site.com ait activé le CORS.
async et les modules
Le mot clé async permet de télécharger en parallèle un script javascript externe, mais ne s’utilise pas pour les script inline (à même la page HTML). dans le cas des modules, le mot clé async s’applique aussi aux Javascript inline.
<script async type="module"> import {counter} from './utils.js'; counter.count(); </script>