Publié par

Il y a 3 années -

Temps de lecture 3 minutes

Si, il faut utiliser les imports nommés en ES6 !

javascript, ES6

Ce billet est une réponse à cet article (en anglais) conseillant de ne pas utiliser les imports nommés en ES6, c’est-à-dire la syntaxe :

import { prop1, prop2 } from 'module';

et de plutôt privilégier l’import * :

import * as module from 'module';

Nous allons voir en quoi ceci est une erreur !

Pourquoi ?

Outre l’argument de clarté du code avec une déclaration explicite de vos dépendances, si vous utilisez un packageur JS récent tel que Webpack, JSPM ou Rollup, il existe une raison qui, à elle seule, justifie leur utilisation : le tree-shaking.

C’est quoi, le tree-shaking ?

Le module pattern ES6 permet de faire de l’analyse statique de vos imports/exports. En explicitant quelles sont les entités dont vous avez besoin grâce aux imports nommés, les outils faisant du tree-shaking vont éliminer les exports qui ne sont jamais importés, mais pas avec la syntaxe import *.

Cela permet d’alléger votre bundle final, parfois énormément si vous n’utilisez qu’une petite partie d’une grosse librairie.

Vous voulez en être sûrs ? J’ai testé pour vous, et vous pouvez tester aussi avec ce repo git.

Dedans, deux exemples. Chacun utilise un module math.js exportant deux méthodes : add et minus, mais seule la méthode add est utilisée. La différence est que le premier utilise un import nommé pour add et l’autre la syntaxe import *. Ce qui est intéressant, c’est le bundle généré par Webpack (en version 2), notamment la ligne définissant les exports :

Version avec import nommé :

/* harmony export */ exports["a"] = add;/* unused harmony export minus */

Version avec import * :

/* harmony export */ exports["add"] = add;/* harmony export */ exports["minus"] = minus;

Avec l’import nommé, Webpack est capable de comprendre que la méthode minus n’est jamais utilisée. Après une étape supplémentaire de minification, le bundle ne contiendra plus du tout cette méthode !

Si vous n’avez pas besoin de tree-shaking, par exemple si vous faites du NodeJS, ce n’est qu’une question de préférence. Mais avec le bon IDE, un ctrl/pomme clic sur le nom de l’import vous amène directement à la déclaration, et c’est quand même pratique.

Il paraît que c’est dur de stubber des imports nommés

C’est ce qu’affirme l’article cité en introduction. Que nenni ! C’est aussi simple qu’avec la syntaxe import * ou qu’avec un simple require CommonJS.

L’article dit notamment que l’export nommé revient à écraser module.exports avec une function, une erreur à ne pas commettre si on veut pouvoir tester . Toujours dans le même repo, voyons le code de math.js exportant les fonctions add et minus, compilé par babel :

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.add = add;
exports.minus = minus;
function add(a, b) {
  return a + b;
}

function minus(a, b) {
  return a - b;
}

Le code compilé définit bien exports.add et exports.minus, sans écraser module.exports. Mais ceci est commun entre l’import nommé et l’import *.

Voyons maintenant le code compilé du module utilisant l’import nommé :

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.add3 = add3;

var _math = require('./math');

function add3(n) {
  return (0, _math.add)(n, 3);
}

Le module est importé dans la variable _math via un require CommonJS, et la méthode add est utilisée plus loin.

Au final on se retrouve avec du code très simple à tester/stubber, avec les habituels mocha/chai/sinon :

import {expect} from 'chai';
import sinon from 'sinon';

import * as math from './math';
import * as app from './app';

describe('app', () => {

  it('should not mock add', () => {
    expect(app.add3(5)).to.equal(8);
  });

  it('should mock add', () => {
    sinon.stub(math, 'add').returns(5); // it works !!
    expect(app.add3(0)).to.equal(5);
  });

});

C’est en fait exactement le même code de test qu’avec l’import *.

tl;dr

En front, utilisez les imports nommés.

En back, faites comme vous voulez.

Publié par

Publié par Anthony Giniers

Anthony est développeur fullstack, Javaiste repenti spécialisé dans les technologies JavaScript et les problématiques liées au Cloud.

Retrouvez le sur Twitter : @aginiers

Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.