在节点中导入需要Babel [英] Importing vs Requiring with Babel in Node

查看:108
本文介绍了在节点中导入需要Babel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在一个文件中导入一个类:

I want to import a class inside one file:

"use strict";
import models from "../model";
class Foo {
    bar() {
    }
}
export default new Foo();

当我使用导入时,它可以工作,如:

It works when I use import, like:

import Foo from "./foo";
console.log(Foo.bar); // [Function bar]

问题是,使用require来给我定义:

The problem is that doing it with require gives me undefined:

var Foo = require("./foo");
console.log(Foo.bar); // undefined

,Foo变量似乎是一个空类。为什么?发生了什么?

and the Foo variable seems to be an empty class. Why is that so? What's going on?

推荐答案

TL; DR



导入 import require 不同。当您从Y导入语法 import X的模块时,会自动导入默认导出,因为语法是根据规范导入默认导出。但是,当您需要时,默认导出是自动导入,就像您所期望的那样。您必须添加 .default 以使用 require 获得默认导出,如: require(。 / foo)。default

TL;DR

This is because importing with import is different than require. When you import a module with the syntax import X from "Y", the default export is automatically imported, as the syntax is meant to import the default export by specification. However, when you require, the default export is not automatically imported like you'd expect. You must add .default to get the default export with require like: require("./foo").default.

Babel transpiles 的示例代码如何:

export { x }

成为:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.x = x;

这是有道理的,因为 x 刚刚导出一般。然后你会继续做:

This makes sense as x is just exported normally. Then you would proceed to do:

require("module").x;

收到 x 。同样,请尝试以下操作:

To receive x. Similarly, try the following:

export default new Foo();

这变成:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = new Foo();

您将看到默认导出附加到 exports 对象作为名为默认的属性,正如 x 导出的属性 X 。这意味着,要获得默认导出与需要,您需要做:

You'll see that the default export is attached to the exports object as a property named default, just as x was exported with property x. That means, to get the default export with require, you'll need to do:

require("module").default;

现在来解释为什么它是 undefined 。在行中:

Now to explain the why it's undefined. In the line:

var Foo = require("./foo");

Foo 这里其实只是一个对象一个默认值属性:

Foo here is actually just an object with a default property:

{
    default: //Whatever was exported as default
}

因此,试图做因为没有 bar 属性,Foo.bar 将会生成 undefined 。您需要访问默认属性才能访问您的实例。

Thus, trying to do Foo.bar will yield undefined because there is no bar property. You need to access the default property to access your instance.

您可能会认为这有点笨重,其他也做。这就是为什么有一个插件来摆脱对额外的需求 .DEFAULT 。该插件执行 module.exports = exports [default] module.exports 从ES5分配到 export [default] 1

You might think this is a little clunky, and other do too. That's why there's a plugin to get rid of the need for the extra .default. The plugin does module.exports = exports["default"] to assign the module.exports from ES5, to exports["default"].1

对于 import 语法,Babel执行以下转换:

For import syntax, Babel does the following transpilation:

import Foo from "./foo";
Foo.bar();

成为:

"use strict";

var _foo = require("./foo");

var _foo2 = _interopRequireDefault(_foo);

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

_foo2.default.bar();

要一行一行地排除它,Babel只需 require 的模块。然后,它在模块上调用 _interopRequireDefault 。支票使用 obj&&&& obj .__ esModule ,以确保模块实际导出任何内容,并使用ES2015 / ES6语法导出模块。如果是,那么模块将按原样返回,否则返回 {default:obj} 。这是为了确保ES515中的 module.exports = x 在ES2015 / ES6中与 export default x 相同。您会注意到,对于默认导入语法,Babel自动添加 .default 以检索默认导出。

To break it down line by line, Babel just requires the module. Then, it calls _interopRequireDefault on the module. A check is done with obj && obj.__esModule to make sure that the module actually exports anything and the module is exported with ES2015/ES6 syntax. If it is, then the module is returned as is, or else { default: obj } is returned. This is to ensure that module.exports = x in ES5 is treated the same as export default x in ES2015/ES6. You'll notice that for default import syntax, Babel automatically adds .default to retrieve the default export.

然而,相应的代码需要

var Foo = require("./foo");
Foo.bar();

是完全有效的ES5代码,所以没有任何东西被淹没。因此,使用 .default 不会添加到 Foo 中。因此,不检索默认导出。

Is completely valid ES5 code, so nothing is transpiled. Consequently, .default is never added to Foo when it is used. Thus, the default export is not retrieved.

1 应该注意的是, module.exports export 只是引用同一个对象,参见这个答案 module.exports 保存从模块导出的数据。 module.exports = x 成功导出 x 为默认值,而不需要额外的$ code > .default require 是因为您将 module.exports 分配给一个一件事由于 module.exports 保存导入的数据, require(module)导入任何 module.exports x 。如果 module.exports 为3,则 require(module)将为3.如果 module.exports 是一个对象,如 {blah:foo} ,然后 require(module)将是 {blah:foo} 。默认情况下, module module.exports 是对象。

1It should be noted that module.exports and exports just refer to the same object, see this answer. module.exports holds the data which is exported from the module. The reason why module.exports = x successfully exports x as default and does not need the extra .default on require is because you're assigning the module.exports to one single thing. Since module.exports holds the data that's imported, require("module") imports whatever module.exports is, which is x. If module.exports were 3, then require("module") would be 3. If module.exports were an object like { blah: "foo" }, then require("module") would be { blah: "foo" }. By default, module and module.exports are objects.

另一方面, exports.default 导出一个对象(引用与相同的对象)module.exports )与一个默认的属性保存默认导出。您可能需要执行 exports = x 以导出 x 作为默认值,但由于 export 被分配给 module.exports 的引用,这将打破引用,导出将不再指向到 module.exports

One the other hand, exports.default exports an object (that refers to the same object as module.exports) with a default property that holds the default export. You may want to do exports = x to export x as default but since exports is assigned a reference to module.exports this will break the reference and exports will no longer point to module.exports.

这篇关于在节点中导入需要Babel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆