2015-11-03 3 views
175

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

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

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

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

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

Спасибо!

Пример:

Входной сигнал:

const foo = {} 
export default foo 

Вывод с Вавилонской 5

"use strict"; 

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

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

"use strict"; 

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

Обратите внимание, что только разница в t он выводит module.exports = exports["default"].


Редактировать

Вы можете быть заинтересованы в этом BlogPost я написал после того, как решить мой конкретный вопрос: Misunderstanding ES6 Modules, Upgrading Babel, Tears, and a Solution

+0

Мне любопытно, какие случаи, когда нужно 'требуют 'если вы работаете в базе кода, которая использует Babel? Скорее всего, есть и другие подходы, которые позволят вам избежать этого. – loganfsmyth

+0

Я использую функцию Webpack, которая не требует кода, если она найдена в мертвом коде, например: 'if (false) {require ('./ foo')}', поскольку webpack пропустил бы фактически, включая 'foo.js' в результирующий пучок. – kentcdodds

+0

В чем дело? Если это условие доступно в вашей конфигурации webpack, может быть другой вариант. – loganfsmyth

ответ

77

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

+1

Я знал, что кто-то напишет плагин рано или поздно. Благодаря! – kentcdodds

+0

К сожалению, babel-plugin-add-module-exports не поддерживает модули amd-стиля (пока) – zowers

+2

Я использовал [babel-plugin-transform-es2015-modules-simple-amd] (https: // www. npmjs.com/package/babel-plugin-transform-es2015-modules-simple-amd), чтобы решить эту же проблему в моем проекте с модулями AMD –

92

Если вы хотите поведение экспорта 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} 
+0

Я согласен с вами (и отметил), что предыдущее поведение было неправильным, но мой вопрос состоял в том, как обойти эту проблему. Я сильно полагался на неправильное поведение (не понимал, что это было неправильно до сегодняшнего утра).Я бы предпочел не обновлять все сразу ... – kentcdodds

+0

Единственное исправление, чтобы получить текущее поведение, было бы переключить ваш код на использование CommonJS напрямую или остаться на Babel 5 до тех пор, пока у вас не будет времени для обновления. – loganfsmyth

+4

@kentcdodds мы можем написать загрузчик веб-пакетов, чтобы это работало (или плагин babel). Я удивлен, что они не предоставляют (или публикуют изменения в большей степени!) –

30

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

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

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

Чтобы обойти эту проблему Бабеля, я изменил это на import заявления, а затем назначить по умолчанию на module.exports:

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

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

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

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

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

+0

По какой-то причине у меня никогда не возникало головокружений прямо о файлах 'module.exports' и' export default'. Теперь мы вернулись на круги своя? – windmaomao

+0

@windmaomao, что вы имеете в виду? Это трюк, так что пользователям commonjs не нужно «требовать (« что угодно »). Default'. Если вы не автор библиотеки, это, вероятно, не имеет значения. – WickyNilliams

0

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

//src/arithmetic.js

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

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

//src/main.js

import { operations } from './arithmetic'; 

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

console.log(result); 
Смежные вопросы