Babel 6 ändert die Art und Weise, wie es standardmäßig exportiert

195

Vorher fügte Babel die Zeile hinzu module.exports = exports["default"]. Das macht es nicht mehr. Was dies bedeutet, ist bevor ich tun konnte:

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

Jetzt muss ich das machen:

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

Keine große Sache (und ich vermute, das hätte es die ganze Zeit sein sollen). Das Problem ist, dass ich viel Code habe, der davon abhängt, wie die Dinge früher funktionierten (ich kann das meiste davon in ES6-Importe konvertieren, aber nicht alles). Kann mir jemand Tipps geben, wie man die alte Art zum Laufen bringt, ohne mein Projekt durchgehen und dies beheben zu müssen (oder sogar eine Anleitung, wie man ein Codemod schreibt, um dies zu tun, wäre ziemlich schlau).

Vielen Dank!

Beispiel:

Eingang:

const foo = {}
export default foo

Ausgabe mit Babel 5

"use strict";

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

Ausgabe mit Babel 6 (und es2015 Plugin):

"use strict";

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

Beachten Sie, dass der einzige Unterschied in der Ausgabe die ist module.exports = exports["default"].


Bearbeiten

Vielleicht interessiert Sie dieser Blogpost, den ich geschrieben habe, nachdem ich mein spezielles Problem gelöst habe: Missverständnis von ES6-Modulen, Aktualisieren von Babel, Tränen und eine Lösung

kentcdodds
quelle
Ich bin gespannt, was sind die Fälle, in denen requireSie arbeiten müssen, wenn Sie in einer Codebasis arbeiten, die Babel verwendet? Möglicherweise gibt es andere Ansätze, mit denen Sie dies ohnehin vermeiden können.
Loganfsmyth
Ich nutze eine Funktion von Webpack, für die kein Code erforderlich ist, wenn sie in totem Code enthalten ist, z. if (false) { require('./foo') }B .: Mit Webpack wird das tatsächliche Einfügen foo.jsin das resultierende Bundle übersprungen .
Kentcdodds
Was ist dein falseUmschalter dort? Wenn es sich um eine Bedingung handelt, die in Ihrer Webpack-Konfiguration verfügbar ist, gibt es möglicherweise eine andere Option.
Loganfsmyth
Dieser hat mich auch gebissen. Danke @kentcdodds.
Tyler McGinnis
1
Dieser verursachte mir stundenlang Probleme, bevor ich diesen Beitrag fand. Am Ende habe ich alle meine export default {foo, bar}durch ersetzt module.exports = {foo, bar}. Mir hat die falsche Methode sehr gut gefallen , die jetzt nicht unterstützt wird.
stolpern

Antworten:

90

Sie können dieses Plugin auch verwenden , um das alte exportVerhalten wiederherzustellen.

SimenB
quelle
1
Ich wusste, dass jemand früher oder später ein Plugin schreiben würde. Vielen Dank!
Kentcdodds
Leider unterstützt Babel-Plugin-Add-Modul-Exporte (noch) keine
AMD
3
Ich habe das babel-plugin-transform-es2015-modules-simple-amd verwendet , um dasselbe Problem in meinem Projekt zu lösen, das AMD-Module enthält
Tom Wayson
Ich denke mit UMD und diesem Plugin ist der richtige Weg! Vielen Dank
Electronix384128
Sehr sehr hilfreich.
Jovica Aleksic
105

Wenn Sie das CommonJS-Exportverhalten wünschen, müssen Sie CommonJS direkt verwenden (oder das Plugin in der anderen Antwort verwenden). Dieses Verhalten wurde entfernt, weil es Verwirrung stiftete und zu einer ungültigen ES6-Semantik führte, auf die sich einige Leute verlassen hatten, z

export default {
  a: 'foo'
};

und dann

import {a} from './foo';

Dies ist ungültiges ES6, funktionierte jedoch aufgrund des von Ihnen beschriebenen CommonJS-Interoperabilitätsverhaltens. Leider ist es nicht möglich, beide Fälle zu unterstützen, und es ist schlimmer, wenn Benutzer ungültiges ES6 schreiben können, als wenn Sie dies tun .default.

Das andere Problem war, dass es für Benutzer unerwartet war, wenn sie beispielsweise in Zukunft einen benannten Export hinzufügten

export default 4;

dann

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

aber

export default 4;
export var foo = 5;

dann

require('./mod')
// {'default': 4, foo: 5}
loganfsmyth
quelle
Ich stimme Ihnen zu (und habe festgestellt), dass das vorherige Verhalten falsch war, aber meine Frage war, wie ich das Problem umgehen kann. Ich habe mich stark auf das falsche Verhalten verlassen (wusste erst heute Morgen, dass es falsch war). Ich würde es vorziehen, nicht alles auf einmal aktualisieren zu müssen ...
kentcdodds
Die einzige Lösung, um das aktuelle Verhalten zu erhalten, besteht darin, Ihren Code so zu ändern, dass er CommonJS direkt verwendet, oder auf Babel 5 zu bleiben, bis Sie Zeit für ein Update haben.
Loganfsmyth
4
@kentcdodds können wir einen Webpack-Loader schreiben, damit dies funktioniert (oder ein Babel-Plugin). Ich bin überrascht, dass sie keine bereitstellen (oder die Änderung stärker veröffentlichen!)
Jamund Ferguson
Ich bin verwirrt darüber ... wenn ich es export default function () {}in Modul A und dann import a from 'a'in Modul B mache , awäre Babel 6 { default: function () {} }... Soweit ich aus exploringjs.com/es6/… verstehen kann , sollte dies funktionieren und ich sollte das exportieren Funktion in B, nicht das Objekt.
Mamapitufo
@mamapitufo Das sollte funktionieren, aber es ist schwer zu sagen, was falsch ist, ohne ein Beispiel anzuschauen. Wenn Sie chatten möchten, können Sie gerne bei Babels Support-Kanal auf Slack vorbeischauen.
Loganfsmyth
33

Für Bibliotheksautoren können Sie dieses Problem möglicherweise umgehen.

Normalerweise habe ich einen Einstiegspunkt, dh index.jsdie Datei, auf die ich aus dem Hauptfeld in zeige package.json. Es wird nichts anderes getan, als den tatsächlichen Einstiegspunkt der Bibliothek erneut zu exportieren:

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

Um das Babel-Problem zu umgehen, habe ich dies in eine importAnweisung geändert und dann die Standardeinstellung zugewiesen module.exports:

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

Alle meine anderen Dateien bleiben als reine ES6-Module ohne Problemumgehungen. Also muss nur der Einstiegspunkt leicht geändert werden :)

Dies funktioniert sowohl für CommonJs als auch für ES6-Importe, da Babel das Reverse Interop (commonjs -> es6) anscheinend nicht gelöscht hat. Babel injiziert die folgende Funktion, um Commonjs zu reparieren:

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

Ich habe Stunden damit verbracht, dagegen anzukämpfen, also hoffe ich, dass dies jemand anderem die Mühe erspart!

WickyNilliams
quelle
Aus irgendeinem Grund habe ich meine Köpfe nie richtig herumgedreht module.exportsund so export default. Jetzt sind wir wieder auf dem ersten Platz?
Windmaomao
@windmaomao was meinst du? Dies ist ein Trick, damit Benutzer von commonjs nicht müssen require("whatever").default. Wenn Sie kein Bibliotheksautor sind, ist dies wahrscheinlich irrelevant
WickyNilliams
1

Ich hatte solche Probleme. Und das ist meine Lösung:

//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);
Ihor Pavlyk
quelle