usar nodejs node modules exports example es6 como node.js module ecmascript-6

node.js - nodejs - node js export modules



module.exports vs. export default en Node.js y ES6 (2)

¿Cuál es la diferencia entre module.exports de module.exports y el export default de ES6? Estoy tratando de averiguar por qué aparece el error "__ no es un constructor" cuando intento export default en Node.js 6.2.2.

Que funciona

''use strict'' class SlimShady { constructor(options) { this._options = options } sayName() { return ''My name is Slim Shady.'' } } // This works module.exports = SlimShady

Lo que no funciona

''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


El problema es con

  • cómo se emulan los módulos ES6 en CommonJS
  • cómo importas el módulo

ES6 a CommonJS

Al momento de escribir esto, ningún entorno admite módulos ES6 de forma nativa. Al usarlos en Node.js, debe usar algo como Babel para convertir los módulos a CommonJS. Pero, ¿cómo sucede eso exactamente?

Mucha gente considera que module.exports = ... es equivalente al export default ... y export default ... exports.foo ... es equivalente a export const foo = ... Sin embargo, eso no es del todo cierto, o al menos no cómo lo hace Babel.

Las exportaciones default ES6 en realidad también se denominan exportaciones, excepto que el default es un nombre "reservado" y hay un soporte especial de sintaxis para ello. Veamos cómo compila Babel las exportaciones con nombre y predeterminadas:

// 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;

Aquí podemos ver que la exportación predeterminada se convierte en una propiedad en el objeto de exports , al igual que foo .

Importar el módulo

Podemos importar el módulo de dos maneras: usando CommonJS o usando la sintaxis de import ES6.

Su problema: creo que está haciendo algo como:

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

esperando que a la bar se le asigne el valor de la exportación predeterminada. Pero como podemos ver en el ejemplo anterior, ¡la exportación predeterminada se asigna a la propiedad default !

Entonces, para acceder a la exportación predeterminada, en realidad tenemos que hacer

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

Si usamos la sintaxis del módulo ES6, a saber

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

Babel lo transformará a

''use strict''; var _input = require(''./input''); var _input2 = _interopRequireDefault(_input); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } console.log(_input2.default);

Puede ver que cada acceso a la bar se convierte en acceso .default .


tl; dr ahora para que esto funcione, el archivo que requiere o importa SlimShady debe compilarse usando Babel con ''use strict'' .

Estoy usando babel-cli 6.18.0 en el proyecto donde inicialmente encontré este error.

Sin ''use strict'' es Bad News Bears

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

''uso estricto'', por favor

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