Babel 6 cambia la modalità di esportazione predefinita


195

Prima Babel avrebbe aggiunto la linea module.exports = exports["default"]. Non lo fa più. Ciò significa che prima che potessi fare:

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

Ora devo fare questo:

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

Non è un grosso problema (e suppongo che questo sia quello che avrebbe dovuto essere da sempre). Il problema è che ho un sacco di codice che dipendeva dal modo in cui le cose funzionavano (posso convertire gran parte di esso in importazioni ES6, ma non tutto). Qualcuno può darmi consigli su come far funzionare il vecchio modo senza dover passare attraverso il mio progetto e risolvere questo problema (o anche alcune istruzioni su come scrivere un codice per fare questo sarebbe piuttosto semplice).

Grazie!

Esempio:

Ingresso:

const foo = {}
export default foo

Uscita con Babele 5

"use strict";

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

Uscita con Babel 6 (e plugin es2015):

"use strict";

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

Si noti che l'unica differenza nell'output è il module.exports = exports["default"].


modificare

Potresti essere interessato a questo post sul blog che ho scritto dopo aver risolto il mio problema specifico: incomprensione dei moduli ES6, aggiornamento di Babel, lacrime e una soluzione


Sono curioso, quali sono i casi in cui sono necessari requirese si lavora in una base di codice che utilizza Babel? È probabile che ci siano altri approcci che ti permetterebbero di evitarlo comunque.
loganfsmyth,

Sto sfruttando una funzionalità di Webpack che non richiederà codice se si trova in un codice morto come: if (false) { require('./foo') }con webpack salterebbe effettivamente incluso foo.jsnel pacchetto risultante.
kentcdodds

Cosa finisce per essere il tuo falseinterruttore qui? Se è una condizione disponibile nella configurazione del tuo webpack, potrebbe esserci un'altra opzione.
loganfsmyth,

Anche questo mi ha morso. Grazie @kentcdodds.
Tyler McGinnis,

1
Questo mi ha causato problemi per ore prima di trovare questo post. Ho finito per sostituire tutto export default {foo, bar}con module.exports = {foo, bar}. Mi è piaciuto molto il metodo errato che ora non è supportato.
inciampare il

Risposte:


90

Puoi anche usare questo plugin per riavere il vecchio exportcomportamento.


1
Sapevo che qualcuno avrebbe scritto un plugin prima o poi. Grazie!
kentcdodds

purtroppo babel-plugin-add-module-exports non supporta i moduli in stile amd (ancora)
zowers

3
Ho usato babel-plugin-transform-es2015-modules-simple-amd per risolvere lo stesso problema nel mio progetto che ha moduli AMD
Tom Wayson,

Penso che usando UMD e questo plugin sia la strada da percorrere! Grazie
electronix384128,

Molto molto utile.
Jovica Aleksic,

105

Se si desidera il comportamento di esportazione di CommonJS, è necessario utilizzare direttamente CommonJS (o utilizzare il plug-in nell'altra risposta). Questo comportamento è stato rimosso perché causava confusione e portava a una semantica ES6 non valida, su cui alcune persone avevano fatto affidamento, ad es

export default {
  a: 'foo'
};

e poi

import {a} from './foo';

che non è valido ES6 ma ha funzionato a causa del comportamento di interoperabilità CommonJS che stai descrivendo. Sfortunatamente non è possibile supportare entrambi i casi e consentire alle persone di scrivere ES6 non valido è un problema peggiore di quello che ti spinge a farlo .default.

L'altro problema era che era inaspettato per gli utenti se, ad esempio, avessero aggiunto un'esportazione denominata in futuro

export default 4;

poi

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

ma

export default 4;
export var foo = 5;

poi

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

Sono d'accordo con te (e ho notato) che il comportamento precedente era errato, ma la mia domanda era come aggirare il problema. Facevo molto affidamento sul comportamento errato (non mi ero reso conto che non era corretto fino a stamattina). Preferirei non dover aggiornare tutto tutto in una volta ...
kentcdodds,

L'unica correzione per ottenere il comportamento attuale sarebbe quella di cambiare il codice per utilizzare direttamente CommonJS o rimanere su Babel 5 fino a quando non si ha il tempo di aggiornare.
loganfsmyth,

4
@kentcdodds possiamo scrivere un caricatore di webpack per farlo funzionare (o un plugin babel). Sono sorpreso che non ne stiano fornendo uno (o pubblicizzando il cambiamento più pesantemente!)
Jamund Ferguson,

Sono confuso da questo ... se lo facessi export default function () {}nel modulo A e poi import a from 'a'nel modulo B, con Babele 6 asarebbe { default: function () {} }... Da quello che posso capire da exploringjs.com/es6/… questo dovrebbe funzionare e dovrei esportare funzione in B, non l'oggetto.
mamapitufo,

@mamapitufo Dovrebbe funzionare, ma è difficile dire cosa c'è di sbagliato senza un esempio da guardare. Sentiti libero di passare dal canale di supporto di Babel su Slack se vuoi chattare.
loganfsmyth,

33

Per gli autori delle biblioteche potresti essere in grado di aggirare questo problema.

Di solito ho un punto di ingresso index.js, che è il file che indico dal campo principale in package.json. Non fa altro che riesportare l'effettivo punto di ingresso della libreria:

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

Per ovviare al problema babel, l'ho modificato in importun'istruzione e quindi assegnato il valore predefinito a module.exports:

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

Tutti i miei altri file rimangono come moduli ES6 puri, senza soluzioni alternative. Quindi solo il punto di ingresso deve essere leggermente modificato :)

Questo funzionerà per i commonjs richiesti, e anche per le importazioni ES6 perché babel non sembra aver lasciato cadere l'interoper inversa (commonjs -> es6). Babel inietta la seguente funzione per patchare commonjs:

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

Ho passato ore a combattere questo, quindi spero che questo risparmi a qualcun altro lo sforzo!


Per qualche ragione, non mi sono mai fatto girare la testa module.exportse export defaultcose del genere. Ora siamo tornati al punto di partenza?
windmaomao

@windmaomao cosa intendi? Questo è un trucco in modo che gli utenti commonjs non debbano farlo require("whatever").default. Se non sei un autore di librerie, questo è probabilmente irrilevante
WickyNilliams,

1

Ho avuto questo tipo di problema. E questa è la mia soluzione:

//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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.