Babel 6更改默认导出方式


195

以前,babel将添加这行module.exports = exports["default"]。它不再这样做。这意味着在我不能做之前:

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

现在,我必须这样做:

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

没什么大不了的(我猜这就是应该一直以来的样子)。问题是我有很多代码取决于事情的工作方式(我可以将大多数代码转换为ES6导入,但不是全部)。任何人都可以给我有关如何使旧方法工作的提示,而不必经历我的项目并解决此问题的方法(甚至是一些有关如何编写codemod来做到这一点的说明也很巧妙)。

谢谢!

例:

输入:

const foo = {}
export default foo

使用Babel 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模块,升级Babel,眼泪和解决方案


我很好奇,require如果您在使用Babel的代码库中工作,在什么情况下需要?可能还有其他方法可以让您避免这种情况。
loganfsmyth,2015年

我正在利用Webpack的功能,如果在死代码中找到它,则将不需要代码,例如:if (false) { require('./foo') }使用webpack会实际跳过包含foo.js在结果包中的代码。
kentcdodds

最终导致您false在那里切换?如果您的webpack配置中存在这种情况,则可能还有其他选择。
loganfsmyth,2015年

这一点也给我 谢谢@kentcdodds。
泰勒·麦金尼斯

1
在我找到这篇文章之前,这个问题导致了我几个小时的问题。我结束了更换所有我的export default {foo, bar}module.exports = {foo, bar}。我挺喜欢的不正确这是现在不支持的方法。
stumct's

Answers:


90

您也可以使用此插件恢复旧的export行为。


1
我知道有人迟早会写一个插件。谢谢!
kentcdodds

可悲的是babel-plugin-add-module-exports不支持amd样式的模块(尚未)
zowers 2015年

3
我已经使用babel-plugin-transform-es2015-modules-simple-amd解决了我具有AMD模块的项目中的同一问题
Tom Wayson,2016年

我认为使用UMD和此插件是必经之路!谢谢
electronicix384128

非常非常有帮助。
Jovica Aleksic '18年

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,2015年

4
@kentcdodds,我们可以编写一个webpack加载器来保持此功能(或babel插件)。我很惊讶他们没有提供一个(或者更广泛地宣传更改!)
Jamund Ferguson 2015年

我对此感到困惑...如果我export default function () {}在模块A中执行然后import a from 'a'在模块B中使用Babel 6,a将会{ default: function () {} }...从我从exploringjs.com/es6/的理解中可以看出…… 这应该可行,并且应该将其导出B中的功能,而不是对象。
mamapitufo

@mamapitufo应该可以,但是如果没有示例,很难说出问题所在。如果您想聊天,请随时访问Slack上的Babel支持频道。
loganfsmyth

33

对于图书馆作者,您也许可以解决此问题。

我通常有一个入口点,index.js这是我从中的主字段指向的文件package.json。除了重新导出lib的实际入口点外,它什么也不做:

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

要解决babel问题,我将其更改为一条import语句,然后将默认值分配给module.exports

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

我所有其他文件都保留为纯ES6模块,没有解决方法。因此,仅入口点需要稍微更改:)

这将适用于commonjs要求,也适用于ES6导入,因为babel似乎没有放弃反向互操作(commonjs-> es6)。Babel注入以下函数来修补commonjs:

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

我已经花了数小时与之抗争,所以我希望这可以节省其他人的精力!


出于某种原因,我从来没有得到我的头纺说得对,module.exportsexport 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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.