205 votes

Babel 6 change la façon dont il exporte les données par défaut

Auparavant, babel ajoutait la ligne module.exports = exports["default"] . Il ne le fait plus. Ce que cela signifie, c'est qu'avant que je puisse le faire :

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

Maintenant, je dois faire ça :

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

Ce n'est pas un gros problème (et je suppose que c'est ce que cela aurait dû être depuis le début). Le problème est que j'ai beaucoup de code qui dépendait de la façon dont les choses fonctionnaient auparavant (je peux en convertir la plupart en importations ES6, mais pas toutes). Est-ce que quelqu'un peut me donner des conseils sur la façon de faire fonctionner l'ancienne méthode sans avoir à parcourir mon projet et à corriger cela (ou même des instructions sur la façon d'écrire un codemod pour le faire, ce serait assez génial).

Merci !

Exemple :

Entrée :

const foo = {}
export default foo

Sortie avec Babel 5

"use strict";

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

Sortie avec Babel 6 (et plugin es2015) :

"use strict";

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

Notez que la seule différence dans la sortie est le module.exports = exports["default"] .


Editar

Vous serez peut-être intéressé par ce billet de blog que j'ai écrit après avoir résolu mon problème spécifique : Comprendre les modules ES6, mettre à niveau Babel, des larmes et une solution

0 votes

Je suis curieux, quels sont les cas où le besoin require si vous travaillez dans une base de code qui utilise Babel ? Il y a de fortes chances qu'il existe d'autres approches qui vous permettraient d'éviter cela de toute façon.

0 votes

Je tire parti d'une fonctionnalité de Webpack qui n'exigera pas le code s'il se trouve dans du code mort comme : if (false) { require('./foo') } avec webpack éviterait d'inclure foo.js dans le faisceau résultant.

0 votes

Ce qui finit par être votre false basculer là ? S'il s'agit d'une condition disponible dans votre configuration webpack, il peut y avoir une autre option.

109voto

loganfsmyth Points 25483

Si vous voulez le comportement d'exportation de CommonJS, vous devrez utiliser CommonJS directement (ou utiliser le plugin dans l'autre réponse). Ce comportement a été supprimé car il était source de confusion et conduisait à une sémantique ES6 invalide, sur laquelle certaines personnes s'étaient appuyées, par exemple

export default {
  a: 'foo'
};

et ensuite

import {a} from './foo';

qui n'est pas valide ES6 mais qui a fonctionné grâce au comportement d'interopérabilité de CommonJS que vous décrivez. Malheureusement, il n'est pas possible de supporter les deux cas, et permettre aux gens d'écrire de l'ES6 invalide est un problème plus grave que de vous faire faire de l'ES6 invalide. .default .

L'autre problème était qu'il était inattendu pour les utilisateurs d'ajouter une exportation nommée à l'avenir, par exemple

export default 4;

puis

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

mais

export default 4;
export var foo = 5;

puis

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

0 votes

Je suis d'accord avec vous (et j'ai noté) que le comportement précédent était incorrect, mais ma question était de savoir comment contourner le problème. Je m'appuyais fortement sur le comportement incorrect (je n'ai réalisé qu'il était incorrect que ce matin). Je préférerais ne pas avoir à tout mettre à jour en une seule fois...

0 votes

La seule solution pour obtenir le comportement actuel serait de modifier votre code pour utiliser CommonJS directement, ou de rester sur Babel 5 jusqu'à ce que vous ayez le temps de faire une mise à jour.

4 votes

@kentcdodds nous pouvons écrire un chargeur webpack pour que cela fonctionne (ou un plugin babel). Je suis surpris qu'ils n'en fournissent pas un (ou qu'ils ne fassent pas plus de publicité pour ce changement !)

94voto

Simen Points 587

Vous pouvez également utiliser ce plugin pour obtenir l'ancien export comportement en retour.

1 votes

Je savais que quelqu'un allait écrire un plugin pour tôt ou tard. Merci !

0 votes

Malheureusement, babel-plugin-add-module-exports ne supporte pas (encore) les modules de style amd.

3 votes

J'ai utilisé le babel-plugin-transform-es2015-modules-simple-amd pour résoudre ce même problème dans mon projet qui comporte des modules AMD

34voto

WickyNilliams Points 2275

Pour les auteurs de bibliothèques, il est possible de contourner ce problème.

J'ai généralement un point d'entrée, index.js qui est le fichier vers lequel je pointe depuis le champ principal dans package.json . Il ne fait rien d'autre que de ré-exporter le point d'entrée réel de la librairie :

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

Pour contourner le problème de babel, j'ai changé ceci en un fichier import et ensuite assigner la valeur par défaut à module.exports :

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

Tous mes autres fichiers restent des modules ES6 purs, sans contournement. Donc seul le point d'entrée doit être légèrement modifié :)

Cela fonctionnera pour les exigences de commonjs, et aussi pour les importations ES6 car babel ne semble pas avoir abandonné l'interopérabilité inverse (commonjs -> es6). Babel injecte la fonction suivante pour corriger commonjs :

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

J'ai passé des heures à me battre contre ce problème, alors j'espère que cela évitera à quelqu'un d'autre de faire cet effort !

0 votes

Pour une raison quelconque, je n'ai jamais eu la tête bien tournée sur module.exports y export default des trucs. Maintenant on est de retour à la case départ ?

0 votes

@windmaomao que voulez-vous dire ? C'est une astuce pour que les utilisateurs de commonjs n'aient pas à require("whatever").default . Si vous n'êtes pas un auteur de bibliothèque, ceci n'est probablement pas pertinent.

2voto

Ihor Pavlyk Points 368

J'ai eu ce genre de problème. Et voici ma solution :

//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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X