在节点中导入需要Babel [英] Importing vs Requiring with Babel in Node
问题描述
我想在一个文件中导入一个类:
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 require
s 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屋!