web-dev-qa-db-fra.com

module.exports et export par défaut dans Node.js et ES6

Quelle est la différence entre module.exports de Node et export default de ES6? J'essaie de comprendre pourquoi l'erreur "__ n'est pas un constructeur" apparaît lorsque j'essaie de export default dans Node.js 6.2.2.

Ce qui fonctionne

'use strict'
class SlimShady {
  constructor(options) {
    this._options = options
  }

  sayName() {
    return 'My name is Slim Shady.'
  }
}

// This works
module.exports = SlimShady

Qu'est-ce que ne fait pas fonctionne

'use strict'
class SlimShady {
  constructor(options) {
    this._options = options
  }

  sayName() {
    return 'My name is Slim Shady.'
  }
}

// This will cause the "SlimShady is not a constructor" error
// if in another file I try `let marshall = new SlimShady()`
export default SlimShady
223
Marty Chang

Le problème est avec

  • comment les modules ES6 sont émulés dans CommonJS
  • comment vous importez le module

ES6 à CommonJS

Au moment de la rédaction de cet article, aucun environnement ne prend en charge les modules ES6 de manière native. Lorsque vous les utilisez dans Node.js, vous devez utiliser quelque chose comme Babel pour convertir les modules en CommonJS. Mais comment ça se passe exactement?

Beaucoup de gens considèrent que module.exports = ... est équivalent à export default ... et exports.foo ... est équivalent à export const foo = .... Ce n'est pas tout à fait vrai cependant, ou du moins pas comment Babel le fait.

Les exportations ES6 default sont en fait également nommées , sauf que default est un nom "réservé" et que sa syntaxe est prise en charge pour ça. Voyons comment Babel compile les exportations nommées et par défaut:

// input
export const foo = 42;
export default 21;

// output
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = exports.foo = 42;
exports.default = 21; 

Nous pouvons voir ici que l'exportation par défaut devient une propriété de l'objet exports, tout comme foo.

Importer le module

Nous pouvons importer le module de deux manières: en utilisant CommonJS ou en utilisant la syntaxe ES6 import.

Votre problème: Je pense que vous faites quelque chose comme:

var bar = require('./input');
new bar();

s’attendant à ce que bar se voit attribuer la valeur de l’export par défaut. Mais comme nous pouvons le voir dans l'exemple ci-dessus, l'exportation par défaut est affectée à la propriété default!

Donc, afin d'accéder à l'exportation par défaut, nous devons réellement faire

var bar = require('./input').default;

Si nous utilisons la syntaxe de module ES6, à savoir

import bar from './input';
console.log(bar);

Babel le transformera en

'use strict';

var _input = require('./input');

var _input2 = _interopRequireDefault(_input);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

console.log(_input2.default);

Vous pouvez voir que chaque accès à bar est converti en accès à .default.

310
Felix Kling