【问题标题】:Babel 6 changes how it exports defaultBabel 6 改变了它导出默认值的方式
【发布时间】:2017-01-16 10:40:41
【问题描述】:

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

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

现在我必须这样做:

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

没什么大不了的(我猜这一直都是应该的)。 问题是我有很多代码取决于过去的工作方式(我可以将大部分代码转换为 ES6 导入,但不是全部)。任何人都可以给我一些提示,告诉我如何让旧方式工作,而不必通过我的项目并修复这个问题(或者甚至一些关于如何编写代码模块来做到这一点的说明会很漂亮)。

谢谢!

例子:

输入:

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"]


编辑

您可能对我在解决我的具体问题后写的这篇博文感兴趣:Misunderstanding ES6 Modules, Upgrading Babel, Tears, and a Solution

【问题讨论】:

  • 我很好奇,如果您在使用 Babel 的代码库中工作,在哪些情况下需要 require?很有可能,还有其他方法可以让您避免这种情况。
  • 我正在利用 Webpack 的一项功能,如果在诸如 if (false) { require('./foo') } 这样的死代码中发现它不需要代码,使用 webpack 会跳过在结果包中实际包含 foo.js
  • 你的false 在那里切换?如果这是您的 webpack 配置中可用的条件,则可能还有另一种选择。
  • 在我找到这篇文章之前,这个问题已经给我带来了几个小时的问题。我最终用module.exports = {foo, bar} 替换了我所有的export default {foo, bar}。我非常喜欢现在不支持的 incorrect 方法。
  • @loganfsmyth 这对于传递整个模块而无需大量重复代码非常有用。看看这个要点gist.github.com/loopmode/3eeaf0764c30439add1d8008e39d0267

标签: ecmascript-6 commonjs babeljs


【解决方案1】:

如果您想要 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}

【讨论】:

  • 我同意你的观点(并指出)之前的行为是不正确的,但我的问题是如何解决这个问题。我严重依赖不正确的行为(直到今天早上才意识到这是不正确的)。我宁愿不必一次更新所有内容...
  • 获得当前行为的唯一解决方法是将您的代码切换为直接使用 CommonJS,或者在您有时间更新之前留在 Babel 5。
  • @kentcdodds 我们可以编写一个 webpack 加载器来保持这个工作(或一个 babel 插件)。我很惊讶他们没有提供一个(或者更强烈地宣传这一变化!)
  • 我对此感到困惑...如果我在模块 A 中执行 export default function () {},然后在模块 B 中执行 import a from 'a',使用 Babel 6 a 将是 { default: function () {} }... 从什么我从exploringjs.com/es6/… 可以理解,这应该可以工作,我应该在 B 中获取导出的函数,而不是对象。
  • @mamapitufo 这应该可以,但是如果没有示例可以说明问题出在哪里。如果您想聊天,请随时访问 Babel 在 Slack 上的支持频道。
【解决方案2】:

您还可以使用 this plugin 恢复旧的 export 行为。

【讨论】:

  • 我知道迟早会有人写一个插件。谢谢!
  • 遗憾的是 babel-plugin-add-module-exports 还不支持 amd 样式的模块
  • 我已经使用babel-plugin-transform-es2015-modules-simple-amd 在我的具有 AMD 模块的项目中解决了同样的问题
  • 我认为使用 UMD 和这个插件是要走的路!谢谢
  • 非常非常有帮助。
【解决方案3】:

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

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

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 你是什么意思?这是一个技巧,因此 commonjs 用户不必require("whatever").default。如果您不是图书馆作者,这可能无关紧要
【解决方案4】:

我遇到过这样的问题。这是我的解决方案:

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

【讨论】:

    猜你喜欢
    • 2016-02-15
    • 2017-09-24
    • 2017-06-09
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多