Babel 6 изменяет способ экспорта по умолчанию

До этого, babel добавит строку module.exports = exports["default"]. Это уже не так. Что это означает, прежде чем я смог:

var foo = require('./foo');
// use foo

Теперь я должен сделать это:

var foo = require('./foo').default;
// use foo

Не огромная сделка (и я предполагаю, что это должно было быть все время). Проблема в том, что у меня много кода, который зависел от того, как все работает (я могу преобразовать большую часть его в импорт ES6, но не все). Может ли кто-нибудь дать мне советы о том, как сделать старый способ работы без необходимости проходить через мой проект и исправить это (или даже некоторая инструкция о том, как писать код, чтобы сделать это, была бы довольно гладкой).

Спасибо!

Пример:

Input:

const foo = {}
export default foo

Выход с Babel 5

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = {};
exports["default"] = foo;
module.exports = exports["default"];

Выход с Babel 6 (и плагин es2015):

"use strict";

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

Обратите внимание, что единственная разница в выходе - module.exports = exports["default"].


Изменить

Возможно, вас заинтересует этот blogpost, который я написал после решения моей конкретной проблемы: Непонимание модулей ES6, обновление Babel, Tears и решение

Ответ 1

Вы также можете использовать этот плагин, чтобы вернуть прежнее поведение export.

Ответ 2

Если вы хотите поведение экспорта CommonJS, вам нужно напрямую использовать CommonJS (или использовать плагин в другом ответе). Это поведение было устранено, поскольку оно вызвало путаницу и привело к недействительной семантике ES6, на которую некоторые люди полагались, например,

export default {
  a: 'foo'
};

а затем

import {a} from './foo';

который является недействительным ES6, но работал из-за поведения совместимости CommonJS, которое вы описываете. К сожалению, поддержка обоих случаев невозможна и позволяет людям писать недействительные ES6, это хуже, чем делать .default.

Другая проблема заключалась в том, что для пользователей было неожиданным, добавили ли они в будущем именованный экспорт, например

export default 4;

затем

require('./mod');
// 4

но

export default 4;
export var foo = 5;

затем

require('./mod')
// {'default': 4, foo: 5}

Ответ 3

Для авторов библиотеки вы можете решить эту проблему.

Обычно у меня есть точка входа, index.js, которая является файлом, на который я указываю, из основного поля в package.json. Он ничего не делает, кроме реэкспорта фактической точки входа lib:

export { default } from "./components/MyComponent";

Чтобы обойти проблему babel, я изменил это на инструкцию import, а затем назначил значение по умолчанию module.exports:

import MyComponent from "./components/MyComponent";
module.exports = MyComponent;

Все мои другие файлы остаются чистыми модулями ES6 без каких-либо обходных решений. Поэтому только точка входа нуждается в изменении немного:)

Это будет работать для commonjs, а также для импорта ES6, потому что бабелей, похоже, не сбросил обратный interop (commonjs → es6). Babel вводит следующую функцию для исправления commonjs:

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

Я потратил часы, сражаясь с этим, поэтому я надеюсь, что это сэкономит кому-то еще усилия!

Ответ 4

У меня была такая проблема. И это мое решение:

//ЦСИ/arithmetic.js

export var operations = {
  add: function (a, b) {
      return a + b;
  },

  subtract: function (a, b) {
      return a - b;
  }
};

//ЦСИ/main.js

import { operations }  from './arithmetic';

let result = operations.add(1, 1);

console.log(result);