448 votes

module.exports vs. export default dans Node.js et ES6

Quelle est la différence entre le système Node module.exports et de l'ES6 export default ? J'essaie de comprendre pourquoi j'obtiens l'erreur "__ is not a constructor" lorsque j'essaie de export default dans Node.js 6.2.2.

Ce qui marche

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

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

// This works
module.exports = SlimShady

Quoi n'a pas travail

'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

542voto

Felix Kling Points 247451

Le problème est le suivant

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

De ES6 à CommonJS

Au moment où nous écrivons ces lignes, 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 cela se passe-t-il exactement ?

De nombreuses personnes considèrent module.exports = ... pour être équivalent à export default ... y exports.foo ... pour être équivalent à export const foo = ... . Ce n'est pas tout à fait vrai, ou du moins pas de la manière dont Babel procède.

ES6 default les exportations sont en fait aussi nommé les exportations, sauf que default est un nom "réservé" et il existe un support syntaxique spécial pour lui. 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; 

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

Importez le module

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

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

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

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

Donc pour accéder à l'exportation par défaut, nous devons en fait faire

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

Si nous utilisons la syntaxe des modules 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 .

0 votes

N'avons-nous pas un duplicata pour cela ?

3 votes

@Bergi : Je n'ai pas cherché (honte à moi :( ). Il y a certainement des questions sur le même problème, mais posées de manière différente. Faites-moi savoir si vous trouvez quelque chose qui vous convient !

1 votes

OK, il a fallu du temps pour les trouver, mais vous pouvez maintenant utiliser vos pouvoirs nouvellement acquis et choisir l'un des éléments suivants Comment utiliser correctement ES6 "export default" avec CommonJS "require" ? y Impossible d'exiger() une valeur d'exportation par défaut dans Babel 6.x comme une cible de dupe :-)

30voto

moein rahimi Points 129

Felix Kling a fait une excellente comparaison de ces deux éléments, pour tous ceux qui se demandent comment faire une exportation par défaut à côté des exportations nommées avec module.exports dans nodejs.

module.exports = new DAO()
module.exports.initDAO = initDAO // append other functions as named export

// now you have
let DAO = require('_/helpers/DAO');
// DAO by default is exported class or function
DAO.initDAO()

0voto

Vous devez configurer babel correctement dans votre projet pour utiliser export default et export const foo.

npm install --save-dev @babel/plugin-proposal-export-default-from

puis ajoutez la configration suivante dans .babelrc

"plugins": [ 
       "@babel/plugin-proposal-export-default-from"
      ]

-47voto

Marty Chang Points 984

Pour l'instant, pour que cela fonctionne, le fichier qui nécessite ou importe SlimShady doit être compilé en utilisant Babel avec 'use strict' .

J'utilise babel-cli 6.18.0 dans le projet où j'ai initialement rencontré cette erreur.

Sans 'use strict' est Bad News Bears

var SlimShady = require('./slim-shady');
var marshall = new SlimShady();  // uh, oh...

"utiliser strictement", s'il vous plaît

'use strict'
import SlimShady from './slim-shady'
var marshall = new SlimShady()  // all good in the hood

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X