Qu’est-ce qu’un module JavaScript (ES6, TypeScript) ?

Vous avez sûrement déjà rencontré le terme de “module”, mais que signifie-t-il exactement dans le contexte du langage JavaScript ?

Le scope GLOBAL (JavaScript ES5)

En JavaScript ES5, il est fréquent qu’on charge plusieurs fichiers .js via une série de balises <script>, et les symboles déclarés dans ces fichiers se retrouvent dans le scope global. Ainsi, un fichier peut facilement accéder aux symboles déclarés dans un autre fichier, pourvu qu’il soit chargé après.

La plupart des librairies JavaScript utilisent le scope global. Prenons l’exemple de jQuery et d’un fichier de code qui utilise cette librairie.

On pourrait charger nos deux fichiers dans une page web de la manière suivante :

<script src="jquery.js"></script>     <!-- Librairie jQuery -->
<script src="my-script.js"></script>  <!-- Mon code -->

jQuery déclare le symbole $ dans le scope global, et comme le fichier my-script.js est chargé après, il peut utiliser le $ :

// my-script.js
$(document).ready(function() {
  console.log("ready!");
});

Cette solution n’est pas très robuste : le code planterait si on inversait l’ordre de chargement des fichiers ; la dépendance de notre fichier à la librairie jQuery n’est pas explicite…

Le scope LOCAL grâce aux modules (JavaScript ES6 / TypeScript)

À partir de JavaScript ES6 (et également avec TypeScript), le scope du code de chaque fichier devient local (on pourrait aussi dire “privé”). Autrement dit, les symboles (classes, fonctions, variables…) déclarés dans un fichier ne sont plus accessibles depuis les autres fichiers.

Ces fichiers au scope local/privé sont appelés des modules.

Autrement dit : 1 module JavaScript/TypeScript = 1 fichier de code.

Un module doit explicitement exporter les symboles qu’il veut rendre accessibles aux autres modules, grâce au mot-clé export. Ici, le module fichier-a.ts exporte la variable firstName, mais pas la variable lastName :

// fichier-a.ts
export const firstName = 'James';  // Accessible depuis les autres modules, car exportée
const lastName = 'Bond';           // Pas accessible depuis les autres modules

Par ailleurs, d’autres modules peuvent accéder aux symboles exportés en les important grâce au mot-clé import. Ici, un autre module (fichier-b.ts) importe la variable firstName et peut ensuite l’utiliser :

// fichier-b.ts
import { firstName } from './fichier-a';

console.log(firstName);

Syntaxe d’un export

N’importe quel symbole nommé peut être exporté d’un module, en précédant sa déclaration du mot-clé export.

// Variable
export const API_KEY = '-wy1LkhpeRz5TqEfI';

// Classe
export class AppComponent { }

// Fonction
export function isAdmin(user: User): boolean { ... }

Syntaxe d’un import

Un import permet d’utiliser localement un symbole déclaré dans un autre module ET exporté de cet autre module. La syntaxe générale repose sur le mot-clé import :

import { symbole } from 'chemin/du/module';

N’oubliez pas les accolades autour du ou des élément(s) importé(s).

On peut importer plusieurs symboles du même module en les séparant par des virgules :

import { Component, Input, Output } from '@angular/core';

Ne précisez pas l’extension du fichier depuis lequel vous importez :

// CORRECT
import { AppModule } from './app/app.module';

// INCORRECT
import { AppModule } from './app/app.module.ts';

Imports relatifs

Les imports relatifs sont résolus par rapport à l’emplacement du fichier courant. Le chemin d’un import relatif commence TOUJOURS par au moins un point “.”.

Dans une application Angular, les imports depuis vos propres fichiers de code sont toujours relatifs.

import { AppModule } from './app/app.module';
import { User } from '../auth';

Imports non relatifs

Les imports non relatifs sont résolus par rapport au répertoire node_modules du projet. Le chemin d’un import non relatif ne commence JAMAIS par un point “.”.

Dans une application Angular, les imports depuis le framework Angular ou depuis des librairies tierce-partie (installées avec npm) sont toujours non relatifs.

// Import depuis Angular
import { Component, Input } from '@angular/core';

// Import depuis la librairie ng-bootstrap
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

NB. Ne pas confondre module JavaScript et module Angular

Un module (en JavaScript ES6 ou en TypeScript) est un fichier dont le code a un scope privé.

Un module Angular est une classe décorée avec @NgModule.

Voir #47 Comprendre la différence entre un module JavaScript et un module Angular.

Informations

Tags : es6typescript

Titres alternatifs :

  • Comment utiliser export et import ?

Dernière mise à jour :

Auteur : AngularChef

Qualité : Bonne