Les modules JavaScript : import et export

Un « module » en programmation correspond à un bloc cohérent de code, c’est-à-dire à un bloc de code qui contient ses propres fonctionnalités fonctionnant ensemble et qui est séparé du reste du code. Généralement, un module possède son propre fichier. L’avantage principal des modules est une meilleure séparation qui résulte dans une meilleure maintenabilité et lisibilité du code.

Le concept de module à proprement parler à longtemps été absent dans le cœur du langage JavaScript. La communauté a donc inventé des procédés différents pour organiser son code de façon à répliquer le comportement des modules tels qu’ils étaient implémentés dans d’autres langages.

Depuis 2015, cependant, les modules font partie des spécifications officielles du langage et possèdent donc des fonctionnalités définies par le JavaScript, ce qui rend leur utilisation beaucoup plus simple et plus puissante.

 

Définition et création de modules JavaScript

Concrètement, un module est un fichier JavaScript qui va exporter certains de ses éléments : fonctions, objets, variables, etc.

Pour utiliser les modules correctement, nous allons devoir respecter quelques règles de syntaxe et utiliser notamment les déclarations export et import dont nous allons préciser le sens par la suite.

Le concept fondamental des modules en JavaScript est qu’on va pouvoir exporter des modules entiers ou des éléments de certains modules (on dit également qu’on « expose » ces éléments) puis les importer dans d’autres scripts.

Ainsi, les modules vont nous donner un contrôle maximal sur ce qui peut être partagé et manipulé et sur ce qui ne doit pas l’être tout en nous fournissant un excellent moyen pour séparer notre code et pour pouvoir le réutiliser dans différents fichiers.

Les éléments d’un module qui peuvent être exportés doivent être précédés de la déclaration export. Pour importer ensuite ces éléments dans d’autres modules, nous allons devoir utiliser la déclaration import suivi nom de l’élément à importer suivi du mot clef from suivi du chemin relatif du fichier importé par rapport au fichier qui l’importe.

Lorsqu’on importe un module dans un fichier HTML, il faut également le préciser dans la balise ouvrante de l’élément script. Créons immédiatement un premier module dans un fichier qu’on va appeler module.js par exemple.

Ce module va contenir deux fonctions : une fonction disBonjour() et une fonction nomComplet(). On va placer l’instruction export devant disBonjour() afin de pouvoir importer cette fonction plus tard.

Création d'un module JavaScript avec export de fonction

Nous allons ensuite importer notre fonction dans notre script principal cours.js. Pour cela, on utilise une instruction import et la syntaxe suivante :

Import d'un module en JavaScript

Notez que si les deux fichiers sont dans le même dossier, il va falloir préciser ./ devant le nom du fichier à importer afin que l’import se passe bien.

Enfin, nous allons également devoir préciser qu’on importe un module au sein de notre fichier HTML en rajoutant un attribut type='module' dans notre élément script.

Import d'un module JavaScript dans un fichier HTML

Note : La plupart des navigateurs bloqueront les imports si vous exécutez ce code localement et sans passer par un serveur pour vous protéger de certaines failles. Si vous voulez tester celui-ci, il vous faudra un serveur (un serveur local suffit). Pour installer une architecture serveur sur votre machine, vous devrez télécharger WAMP (Windows) ou MAMP (Mac).

 

Les fonctionnalités principales des modules

Le mode strict

La première chose à savoir ici est que les modules utilisent par défaut le mode strict en JavaScript.

La portée des modules

Les modules possèdent leur propre espace global de portée. Cela signifie que les variables et fonctions définies dans l’espace global d’un module ne seront par défaut pas accessibles aux autres scripts.

Chaque module devra exporter les éléments qu’il souhaite rendre accessible aux autres fichiers et importer les éléments auxquels il souhaite accéder (sous réserve que ces éléments soient importables).

L’évaluation des modules

Le code des modules n’est évalué qu’une seule fois. Ainsi, si le code d’un module est importé plusieurs fois dans d’autres modules, le code ne va être exécuté qu’une seule fois (par le premier module qui va en avoir besoin) puis le résultat de cette exécution sera ensuite exporté à tous les autres modules ayant importé de même code.

Imaginons par exemple qu’on possède un module qui exporte un objet :

Création d'un module JavaScript avec export d'un objet

On peut ensuite importer cet objet dans n’importe quel autre fichier. Si on l’importe dans deux autres fichiers, par exemple, ce code ne sera évalué qu’une seule fois dans le premier fichier qui va l’utiliser puis le résultat de cette évaluation va être automatiquement exporté et disponible dans l’autre fichier.

Ainsi, le premier fichier qui utilise le code de notre module va créer l’objet et cet objet va ensuite être disponible dans tous les autres fichiers qui importent notre module.

Import d'un module JavaScript dans deux fichiers et évaluation du module

Import d'un module JavaScript dans deux fichiers et évaluation du module

Import d'un module JavaScript depuis deux fichiers dans un fichier HTML

Code illustrant le principe d'évaluation unique des modules JavaScript

Ici, deux fichiers cours.js et cours2.js importent l’objet user de notre module module.js.

Le fichier cours.js va être exécuté en premier par le navigateur. Il affiche le contenu de l’objet importé user.js puis change la valeur du prénom et affiche à nouveau le prénom changé.

Ensuite, le fichier cours2.js importe notre objet et affiche la valeur du prénom. Comme vous pouvez le remarquer, le prénom affiché est bien le prénom modifié par le fichier cours.js.

Les modules utilisent defer

Les modules utilisent defer par défaut lorsqu’ils sont chargés dans le navigateur, ce qui signifie donc que :

  • Les modules importés avec script type="module" src="…" ne bloquent pas l’analyse du code HTML suivant ;
  • Les modules attendent que le document HTML soit complètement chargé pour s’exécuter ;
  • L’ordre des scripts est respecté : le premier module inséré s’exécutera en premier et etc.

L’utilisation d’async avec les modules

Notez qu’on peut également utiliser un attribut async avec les modules afin que ceux-ci s’exécutent de manière asynchrone. Dans ce cas-là, les scripts s’exécuteront dès qu’ils seront prêts.

Cela peut être utile dans le cas où l’on souhaite importer des modules qui sont indépendants du reste de la page (modules de statistique, de publicité, etc.).

 

En résumé

Un module est un bloc de code cohérent et indépendant. En JavaScript, on place chaque module dans un fichier séparé.

On va ensuite pouvoir choisir quels éléments d’un module vont être exposés en les précédant d’une déclaration export. Ces éléments pourront être importés avec import dans d’autres modules ou dans d’autres scripts.

Les modules permettent :

  • Une meilleure maintenabilité du code : par définition un bon module doit être autonome et on doit pouvoir le modifier sans avoir à modifier d’autres scripts ;
  • D’éviter de polluer les autres scripts : les modules possèdent leur propre espace de portée globale et les autres scripts n’y ont pas accès par défaut. Cela permet donc de limiter le risque de pollution (le fait d’avoir de nombreuses variables différentes dans l’espace global du script et de courir le risque que certaines possèdent le même nom) ;
  • Une meilleure réutilisation du code : comme les modules sont indépendants et autonomes (s’ils sont créés correctement), on peut les réutiliser dans différents projets, ce qui nous fait gagner beaucoup de temps.

Laisser un commentaire