Modules JavaScript

et

Module Bunbling

David Soyez @2016

Sommaire

  • Qu'est ce qu'un module?
  • Pourquoi utiliser des modules?
  • Comment coder un module
  • CommonJs et AMD
  • ES2015

Partie 1: Qu'est ce qu'un module?

Partie 2: Module bundling

  • Qu'est ce que le module bundling?
  • Pourquoi empaqueter les modules?
  • Quelles sont les methodes?
  • Bundling CommonJs
  • Bundling AMD
  • Webpack
  • Bundling sous ES2015

Partie 1: Qu'est ce qu'un module?

Partie 1: Qu'est ce qu'un module?

Qu'est ce qu'un module?

De la même manière qu'un bon livre est divisé en chapitres, un bon développeur sépare son code en modules.

 

Un module correctement écrit est autonome, c'est a dire qu'il peut être réutilisé ou supprimé d'un projet sans perturber ce dernier.

Pourquoi utiliser des modules?

  • La maintenance

Puisque un module est autonome, son amélioration et son maintien deviennent plus facile car ne demandant pas de toucher aux autres modules.

  • Les namespaces

Toutes les variables en dehors de fonctions sont globales. Les modules évitent cette pollution en créant des namespaces privé pour ses propres variables.

  • La réutilisation

L'avantage des modules est qu'ils peuvent être réutilisés, partagés et remplacés. Gagnant ainsi en productivité.

Partie 1: Qu'est ce qu'un module?

Comment coder un module?

Différent modules pattern correspondent a différentes méthodes d’écrire un module mais globalement ils sont tous utilisés pour simuler le concept de classes en javascript. Permettant ainsi d'exposer seulement certaines propriétés ou methodes a son utilisateur.

 

Nous allons en voir quelques un d'entre-eux:

  • La fonction anonyme
  • L'import de globale
  • L'interface objet ou Export de module

Partie 1: Qu'est ce qu'un module?

Comment coder un module?

  • La fonction anonyme
(function () {
	// Toutes les variables et fonctions sont uniquement..
        // ..accessibles localement.
	// L’accès au global scope est maintenu.
}());

Cette exemple est le plus courant. Nous créons une fonction anonyme qui est aussitôt exécutée. Tout ce qui réside a l’intérieur est privé et n’interfère pas avec le reste de l'application.

 

Notez que les parenthèses qui englobent cette fonction sont nécessaires pour la définir en tant qu'expression et non comme déclaration de fonction.

Partie 1: Qu'est ce qu'un module?

Comment coder un module?

  • L'import de globale
(function ($) {
    $('body').html("La variable globale jQuery est passée et nommée $");
}(jQuery));

Dans cette exemple au lieu de l'utilisation implicite de variables globales, nous passons la variable globale jQuery en tant que paramètre a la fonction anonyme.

Cette méthode est plus claire et plus rapide évitant ainsi a javascript de traverser le code a la recherche du scope de la variable utilisée.

Partie 1: Qu'est ce qu'un module?

Comment coder un module?

  • L'interface objet ou Export de module
var MonModule = ( function( window ) {

  // cet objet est utilisé pour stocker les variables et methodes privées..
  // ..a travers de multiples instanciations
  var privates = {};
  
  function MonModule() {
    
    this.maMethode = function maMethode() {
      alert( 'ma methode' );
    };

    this.monAutreMethode = function monAutreMethode() {
      alert( 'mon autre methode' );
    };

  }

  return MonModule;
  
} )( window );

var monModule1 = new MonModule();
monModule1.maMethode();
monModule1.monAutreMethode();

Dans cette méthode nous décidons de quelles propriétés ou methodes nous voulons rendre publiques ou privées.

Partie 1: Qu'est ce qu'un module?

CommonJs et AMD

Les approches précédentes ont un point en commun: ils enveloppent leurs codes dans une fonction, permettant ainsi d'avoir leur propre namespace privé.

 

Bien qu’étant efficaces, ces approches ont toutefois des inconvénients. L'un d'entre-eux étant les gestion des dépendances compliquant ainsi la gestion de l'ordre des déclarations de tous les modules.

 

D'autres problèmes peuvent se poser si vous avez deux modules avec le même nom, ou bien si vous avez besoin de deux versions différentes d'un même module.

 

CommonJs et AMD résolvent ces problèmes.

Partie 1: Qu'est ce qu'un module?

CommonJs

CommonJs est un groupe qui définie des API JavaScript pour la déclaration de modules pour des applications hors navigateur.

 

Un module CommonJs est essentiellement un bout de code JavaScript réutilisable qui exporte des objets spécifiques et les rends disponibles a d'autres modules qui les require

C'est ce standard qui a été adopté par NodeJs

 

Chaque fichier JavaScript stocke  ses modules dans son propre et unique contexte. Depuis ce contexte nous exposons les modules grâce a module.exports, ensuite require est utilisé pour les importer.

 

Partie 1: Qu'est ce qu'un module?

CommonJs

function monModule() {
  this.bonjour = function() {
    return 'bonjour!';
  }

  this.auRevoir = function() {
    return 'au revoir!';
  }
}

module.exports = monModule;

Exemple:

Pour declarer notre module afin qu'il puisse etre utilisé dans notre application, nous plaçons une référence dans le systeme CommonJs au moyen de module.exports

 

Ensuite, nous utilisons require pour l'importer:

var monModule = require('monModule');

var module1 = new monModule();
module1.bonjour();
module1.auRevoir();

Partie 1: Qu'est ce qu'un module?

CommonJs

Pour résumer, les deux principaux avantages de CommonJs sont:

  • Isoler le code de chaque module dans son propre namespace
  • Rendre les dépendances explicites

Partie 1: Qu'est ce qu'un module?

AMD

Tandis que CommonJs apporte un standard pour l’écriture de modules JavaScript hors navigateur. Pour être adopté coté navigateur, il faut faire face a deux majeurs problèmes:

  • Le temps chargement réseau
  • Le manque d'asynchrone

 

AMD ou Asynchronous Module Definition a été conçu pour répondre a cette problématique grâce a une syntaxe rapide a comprendre et utiliser.

define(['jquery','monModule'] , function ($, monModule) {
    return function () {};
});

Dans cette exemple, nous importons le module jQuery puis monModule. Ces deux modules sont téléchargés en même temps. C'est une fois les deux modules téléchargés qu'ils seront chargés en asynchrone par JavaScript. Une fois chargés la fonction callback est exécutée.

Partie 1: Qu'est ce qu'un module?

AMD

Notre module écrit précédemment ressemblerait donc a cela:

define([], function() {

  return {
    bonjour: function() {
      console.log('bonjour');
    },
    auRevoir: function() {
      console.log('au revoir');
    }
  };
});

Partie 1: Qu'est ce qu'un module?

ES2015

L’arrivée de ES2015 permet de bénéficier du meilleur de CommonJs et AMD en apportant également des améliorations.

Partie 1: Qu'est ce qu'un module?

La base sur les modules en ES2015:

Il y a deux types d'export de modules en ES2015, les exports nommés (plusieurs par module) et les exports par défaut (un par module)

Bien qu'il soit possible d'utiliser les deux types a la fois, il est préférable d'un utiliser qu'un seul.

ES2015

Partie 1: Qu'est ce qu'un module?

Les exports nommés:

Un module peut exporter plusieurs choses en préfixant ses déclarations par le mot clé export. Ces exports sont différenciés par leurs noms et sont appelés export nommés.

//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';

console.log(square(11)); // 121
console.log(diag(4, 3)); // 5

ES2015

Partie 1: Qu'est ce qu'un module?

Les exports default:

Les modules exportants de simples valeurs sont courant en NodeJs

Ils le sont également dans le développement frontend ou vous pouvez avoir une seule classe par module pour les models ou composants.

//------ myFunc.js ------
export default function () {} // pas de ;

//------ main1.js ------
import myFunc from 'myFunc';
myFunc();

Le module suivant est une fonction:

//------ MyClass.js ------
export default class {} // pas de ;

//------ main2.js ------
import MyClass from 'MyClass';
const inst = new MyClass();

Le module suivant est une classe:

Partie 2: Module bundling

Qu'est ce que le module bundling?

Partie 2: Module bundling

Le module bunbling ou paquetage de module est l'action de regrouper  plusieurs modules et leurs dependances en un seul fichier et dans le bon ordre.

Pourquoi empaqueter les modules?

Partie 2: Module bundling

Quand vous divisez un site en modules, vous organisez généralement vos modules dans des fichiers et répertoires. Il y a des chances pour que vous faites de même avec les modules de librairies comme jQuery, backbone, underscore etc...

De cette façon, vous devez inclure chaque <script> dans votre fichier html ce qui résulte a un téléchargement de chaque fichier individuellement. Ce qui n'est pas idéal pour le temps de chargement.

Pour résoudre ce problème, nous créons un paquet (bundle), concaténons ou réduisons (minify) tous nos fichiers pour réduire le nombre de requêtes.

 

Les task runners comme Grunt ou Gulp permettent d'effectuer ce genre d’opérations.

Quelles sont les methodes?

Partie 2: Module bundling

Concaténer ou minifier vos fichiers peuvent suffire lorsque vous travaillez avec de simples modules patterns pour définir vos modules. Vous utilisez simplement du code natif.

Cependant si vous adhérez a des systèmes que le navigateur ne peut interpréter comme CommonJs, AMD ou même ES2015 vous aurez besoin d'un outil pour convertir vos modules.

C'est la ou intervient Browserify, RequireJS, Webpack, et autres “module bundlers”

Bundling               ?

Partie 2: Module bundling

Comme expliqué précédemment, CommonJs charge les modules en synchrone, ce qui ne convient pas pour un navigateur.

Pour rendre lisible les modules CommonJs par le navigateur, une solution est Browserify. Un module bundler qui permet de compiler les modules CommonJs.

// main.js

var unique = require('uniq');

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

console.log(unique(data));
npm install uniq   // pour installer la dépendance

browserify main.js -o bundle.js   // crée le bundle
<script src="bundle.js"></script>

Exemple:

Bundling AMD?

Partie 2: Module bundling

Si vous utilisez AMD, vous utiliserez probablement RequireJs.

La principale différence entre CommonJs et AMD et que ce dernier charge les modules en asynchrone. Évitant ainsi l’étape de création d'un bundle regroupant tous les modules, et signifiant que chaque module est téléchargé au fur et a mesure de leur nécessité.

Toutefois dans la réalité, il sera préférable de créer un bundle avec l'optimiser r.js afin d’éviter un trop grand nombre de requête http.

// main.js

define(function (require) {
    // Load any app-specific modules
    // with a relative require call,
    // like:
    var messages = require('./messages');

    // Load library/vendor modules using
    // full IDs, like:
    var print = require('print');

    print(messages.getHello());
});
// créer un bundle pour la production
node r.js -o baseUrl=. name=main out=bundle.js
// messages.js

define(function () {
    return {
        getHello: function () {
            return 'Hello World';
        }
    };
});
// print.js

define(function () {
    return function print(msg) {
        console.log(msg);
    };
});

Webpack

Partie 2: Module bundling

Webpack est un des derniers module bundler a être sortie. Il est compatible avec les systèmes modulaires de types CommonJS, AMD, ES2015...

Il fournit plus d'outils que Browserify et RequireJs comme par exemple l'insertion d'images, de fonts ou css dans les modules.

Il dispose également d'outils comparables a Grunt ou Gulp.

Bundling sous ES2015

Partie 2: Module bundling

Contrairement au AMD, les modules en ES2015 sont importés au moment de la compilation du code en subissant un tree shaking permettant d'importer  seulement le code utilisée dans ces modules.

A l'heure actuelle ES2015 ne définie pas encore de quelle façon un module doit être chargée par le navigateur.

Un transpiler comme Babel ou Traceur est alors nécessaire afin de transformer le code ES2015 en ES5 en utilisant le format CommonJS ou AMD.

Ensuite faites passer ce code dans un module bundler comme Browserify ou Webpack pour créer des bundles.

Modules JavaScript et Module Bunbling

By David Soyez

Modules JavaScript et Module Bunbling

  • 727