Вавилон 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.