A questão é com
- como os módulos ES6 são emulados no CommonJS
- como você importa o módulo
ES6 para CommonJS
No momento em que escrevemos isso, nenhum ambiente suporta módulos ES6 nativamente. Ao usá-los no Node.js, você precisa usar algo como Babel para converter os módulos em CommonJS. Mas como exatamente isso acontece?
Muitas pessoas consideram module.exports = ...
ser equivalente export default ...
e exports.foo ...
equivalente export const foo = ...
. Isso não é bem verdade, porém, ou pelo menos não como Babel faz.
default
Na verdade, as exportações do ES6 também são denominadas exportações, exceto que default
é um nome "reservado" e há suporte especial à sintaxe. Vamos ver como o Babel compila exportações nomeadas e padrão:
// 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;
Aqui podemos ver que a exportação padrão se torna uma propriedade no exports
objeto, assim como foo
.
Importar o módulo
Podemos importar o módulo de duas maneiras: Usando CommonJS ou usando a import
sintaxe ES6 .
Seu problema: acredito que você está fazendo algo como:
var bar = require('./input');
new bar();
esperando que bar
seja atribuído o valor da exportação padrão. Mas, como podemos ver no exemplo acima, a exportação padrão é atribuída à default
propriedade!
Portanto, para acessar a exportação padrão, precisamos fazer
var bar = require('./input').default;
Se usarmos a sintaxe do módulo ES6, a saber
import bar from './input';
console.log(bar);
Babel irá transformá-lo em
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
Você pode ver que todo acesso a bar
é convertido em acesso .default
.
module.exports
,exports
emodule.exports
têm valores diferentes, de modo que a atribuição paraexports.defaults
não tem efeito (porquemodule.exports
é o que é exportado). Em outras palavras, é exatamente o mesmo que você fezmodule.exports = { ... }
.Você precisa configurar o babel corretamente no seu projeto para usar o padrão de exportação e o const foo de exportação
adicione abaixo a configração em .babelrc
fonte
Felix Kling fez uma ótima comparação entre os dois, para quem quer saber como fazer um padrão de exportação ao lado de exportações nomeadas com module.exports em nodejs
fonte
Agora, para que isso funcione, o arquivo que está exigindo ou importando
SlimShady
deve ser compilado usando Babel com'use strict'
.Estou usando o
babel-cli
6.18.0 no projeto em que encontrei esse erro inicialmente.Sem
'use strict'
são más notícias'use strict', por favor
fonte
import
declarações é um módulo, e elas já são rigorosas. A diferença real é sobre exigir vs importar.import
vez derequire
e emexport default
vez deexports.default
.