Вавилон 6 змінює спосіб експорту за замовчуванням


195

Раніше вавилон додав би рядок module.exports = exports["default"]. Це більше не робить цього. Що це означає, перш ніж я міг зробити:

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"];

Вихід із Babel 6 (та плагін es2015):

"use strict";

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

Зауважте, що єдиною різницею у виході є module.exports = exports["default"].


Редагувати

Можливо, вас зацікавить цей блог-пост, який я написав після вирішення моєї конкретної проблеми: Нерозуміння модулів ES6, Оновлення Вавілону, Сльози та рішення


Мені цікаво, які випадки потребують, requireякщо ви працюєте в кодовій базі, яка використовує Babel? Швидше за все, є й інші підходи, які дозволять вам уникнути цього в будь-якому випадку.
loganfsmyth

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

Що в кінцевому підсумку стає вашим falseперемиканням там? Якщо це умова, наявна у вашому конфігурації веб-пакету, може бути інший варіант.
loganfsmyth

Цей мене теж покусав. Дякуємо @kentcdodds.
Тайлер МакГінніс

1
Це викликало у мене проблеми години, перш ніж я знайшов цю посаду. Я в кінцевому підсумку замінити всі моє export default {foo, bar}з module.exports = {foo, bar}. Мені дуже сподобався невірний метод, який зараз не підтримується.
stumct

Відповіді:


90

Ви також можете використовувати цей плагін, щоб повернути стару exportповедінку.


1
Я знав, що хтось рано чи пізно напише плагін. Дякую!
kentcdodds

на жаль, babel-plugin-add-module-
export

3
Я використовував модулі babel-plugin-transform-es2015-simple-amd для вирішення цієї самої проблеми в моєму проекті, який має модулі AMD
Том Вейсон

Я думаю, що використовувати UMD і цей плагін - це шлях! Дякую
electronix384128

Дуже дуже корисно.
Йовіца Алексич

105

Якщо ви хочете поведінку експорту 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}

Я погоджуюся з вами (і зазначив), що раніше поведінка була неправильною, але моє питання полягало в тому, як обійти проблему. Я сильно покладався на неправильну поведінку (до цього ранку не усвідомлював, що це було неправильно). Я вважаю за краще не оновлювати все все одразу ...
kentcdodds

Єдине виправлення для отримання поточної поведінки - це переключити свій код на використання CommonJS безпосередньо або залишитися на Babel 5, поки не встигнете оновитись.
loganfsmyth

4
@kentcdodds ми можемо написати завантажувач веб-пакетів, щоб це не працювало (або плагін Babel). Я здивований, що вони не надають цього (або оприлюднюють зміни ще більше!)
Jamund Ferguson

Мене це бентежить ... якщо я export default function () {}в модулі A, а потім import a from 'a'у модулі B, з Babel 6 aбуло б { default: function () {} }... З того, що я можу зрозуміти з exploringjs.com/es6/…, це повинно працювати, і я повинен отримати експортований функція в B, а не об'єкт.
mamapitufo

@mamapitufo Це повинно спрацювати, але важко сказати, що не так, не дивлячись на приклад. Сміливо заїжджайте на канал підтримки Babel на Slack, якщо хочете спілкуватися.
loganfsmyth

33

Для авторів бібліотеки ви зможете вирішити цю проблему.

У мене зазвичай є точка входу index.js, яка є файлом, на який я вказую з головного поля в package.json. Це не що інше, як реекспорт фактичної точки входу lib:

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

Щоб вирішити проблему з дітьми, я змінив це на importзаяву, а потім призначив за замовчуванням module.exports:

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

Усі інші мої файли залишаються чистими модулями ES6, без вирішення проблем. Тож змінити лише точку входу :)

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

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

Я витратив години на боротьбу з цим, тож сподіваюся, що це заощадить чужі зусилля!


Чомусь я ніколи не закручував голову прямо module.exportsта export defaultінше. Тепер ми повернулися до квадратного?
windmaomao

@windmaomao, що ти маєш на увазі? Це хитрість, щоб користувачі commonjs не повинні require("whatever").default. Якщо ви не автор бібліотеки, це, мабуть, не має значення
WickyNilliams

1

У мене були такі проблеми. І це моє рішення:

//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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.