Node.jsおよびES6でのmodule.exportsとexport default


317

Node module.exportsとES6の違いは何export defaultですか?export defaultNode.js 6.2.2で「__はコンストラクターではありません」エラーが発生する理由を理解しようとしています。

機能するもの

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

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

// This works
module.exports = SlimShady

何をしていない仕事

'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

回答:


401

問題は

  • CommonJSでES6モジュールをエミュレートする方法
  • モジュールのインポート方法

ES6からCommonJS

これを書いている時点では、ES6モジュールをネイティブにサポートしている環境はありません。Node.jsで使用する場合は、Babelなどを使用してモジュールをCommonJSに変換する必要があります。しかし、それはどのように正確に起こりますか?

多くの人が考えるmodule.exports = ...に相当するとexport default ...exports.foo ...に相当しますexport const foo = ...。しかし、それは真実ではなく、少なくともバベルのやり方ではありません。

ES6 defaultエクスポートは実際にエクスポートとも呼ばれますが、これdefaultは「予約済み」の名前であり、特別な構文サポートがあることを除きます。Babelが名前付きおよびデフォルトのエクスポートをコンパイルする方法を見てみましょう。

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

ここでは、デフォルトのエクスポートがのexportsようにオブジェクトのプロパティになることがわかりますfoo

モジュールをインポートする

モジュールは2つの方法でインポートできimportます。CommonJSを使用するか、ES6 構文を使用します。

あなたの問題:あなたは次のようなことをしていると思います:

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

barデフォルトのエクスポートの値が割り当てられていることを期待しています。しかし、上の例でわかるように、デフォルトのエクスポートがdefaultプロパティに割り当てられています!

したがって、デフォルトのエクスポートにアクセスするには、実際に行う必要があります

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

つまり、ES6モジュール構文を使用する場合、

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

バベルはそれを

'use strict';

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

var _input2 = _interopRequireDefault(_input);

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

console.log(_input2.default);

へのすべてのアクセスがaccessにbar変換されていることがわかります.default


これの複製はありませんか?
Bergi

3
@Bergi:私はtbhを検索しませんでした(恥ずかしい:()。同じ問題について確かに質問がありますが、別の方法で尋ねられました。適合するものを見つけたらお知らせください!
Felix Kling

1
OK、これらを見つけるのに少し時間がかかりましたが、新しく取得したパワーを使用して、CommonJSの「require」でES6の「export default」を正しく使用する方法を選択できますか?および、バベル6.xのデフォルトのエクスポート値を dupeターゲットとしてrequire()することはできません :-)
Bergi

1
私がこれを今やることができるなんて皮肉なことです:D
フェリックスクリング

1
@djKianoosh: 自分のてください。割り当て後module.exportsexportsおよびmodule.exportsへの割り当てはので、異なる値を持ってexports.defaultsも効果はありません(ので、module.exportsエクスポートされるものです)。言い換えれば、あなたがしただけの場合とまったく同じですmodule.exports = { ... }
Felix Kling 2017年

1

デフォルトのエクスポートを使用してconst fooをエクスポートするには、プロジェクトでbabelを正しく設定する必要があります

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

次に、.babelrcに以下の設定を追加します

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

1

Felix Klingは、nodejsでmodule.exportsを使用して名前付きエクスポートと一緒にデフォルトのエクスポートを行う方法を疑問に思う方のために、これら2つについて優れた比較を行いました

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

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

-61

tl; drこれが機能するためには、必要なファイルまたはインポートするファイルSlimShadyをBabelを使用してコンパイルする必要があります。'use strict'

私は使っています babel-cli最初にこのエラーが発生したプロジェクトで6.18.0をしています。

なし'use strict'でベアーズ

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

「厳格に使用してください」

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

13
これは意味がありません。import宣言を使用するすべてのソースはモジュールであり、それらはすでに厳密です。実際の違いは、要求とインポートの違いです。
Bergi、2016年

1
意味があるのは、のimport代わりにrequireとのexport default代わりにを使用することですexports.default
Corey Alix


104
これは、stackoverflowでこれまでに見た中で最も否定的な回答でなければなりません
Jimi

4
@Jimiこれは、サイト全体で4番目に投票された回答であるためです。
pppery
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.