使用 require() 加载 ECMAScript 模块
¥Loading ECMAScript modules using require()
¥Stability: 1.2 - Release candidate
.mjs
分机保留给 ECMAScript 模块。有关哪些文件被解析为 ECMAScript 模块的更多信息,请参阅 确定模块系统 部分。
¥The .mjs
extension is reserved for ECMAScript Modules.
See Determining module system section for more info
regarding which files are parsed as ECMAScript modules.
require()
仅支持加载满足以下要求的 ECMAScript 模块:
¥require()
only supports loading ECMAScript modules that meet the following requirements:
-
该模块是完全同步的(不包含顶层
await
);and¥The module is fully synchronous (contains no top-level
await
); and -
满足以下条件之一:
¥One of these conditions are met:
-
该文件的扩展名为
.mjs
。¥The file has a
.mjs
extension. -
该文件具有
.js
扩展名,最接近的package.json
包含"type": "module"
¥The file has a
.js
extension, and the closestpackage.json
contains"type": "module"
-
文件具有
.js
扩展名,最接近的package.json
不包含"type": "commonjs"
,并且模块包含 ES 模块语法。¥The file has a
.js
extension, the closestpackage.json
does not contain"type": "commonjs"
, and the module contains ES module syntax.
-
如果正在加载的 ES 模块符合要求,require()
可以加载它并返回 模块命名空间对象。在这种情况下,它与动态 import()
类似,但同步运行并直接返回名称空间对象。
¥If the ES Module being loaded meets the requirements, require()
can load it and
return the module namespace object. In this case it is similar to dynamic
import()
but is run synchronously and returns the name space object
directly.
使用以下 ES 模块:
¥With the following ES Modules:
// distance.mjs
export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); }
// point.mjs
export default class Point {
constructor(x, y) { this.x = x; this.y = y; }
}
CommonJS 模块可以使用 require()
加载它们:
¥A CommonJS module can load them with require()
:
const distance = require('./distance.mjs');
console.log(distance);
// [Module: null prototype] {
// distance: [Function: distance]
// }
const point = require('./point.mjs');
console.log(point);
// [Module: null prototype] {
// default: [class Point],
// __esModule: true,
// }
为了与将 ES 模块转换为 CommonJS 的现有工具进行互操作,然后可以通过 require()
加载真正的 ES 模块,返回的命名空间将包含 __esModule: true
属性(如果它具有 default
导出),以便使用工具生成的代码可以识别真实 ES 模块中的默认导出。如果命名空间已经定义了 __esModule
,则不会添加。此属性是实验性的,将来可能会发生变化。它应该只由将 ES 模块转换为 CommonJS 模块的工具使用,遵循现有的生态系统惯例。直接用 CommonJS 编写的代码应避免依赖它。
¥For interoperability with existing tools that convert ES Modules into CommonJS,
which could then load real ES Modules through require()
, the returned namespace
would contain a __esModule: true
property if it has a default
export so that
consuming code generated by tools can recognize the default exports in real
ES Modules. If the namespace already defines __esModule
, this would not be added.
This property is experimental and can change in the future. It should only be used
by tools converting ES modules into CommonJS modules, following existing ecosystem
conventions. Code authored directly in CommonJS should avoid depending on it.
当 ES 模块同时包含命名导出和默认导出时,require()
返回的结果是 模块命名空间对象,它将默认导出放在 .default
属性中,类似于 import()
返回的结果。要自定义 require(esm)
应直接返回的内容,ES 模块可以使用字符串名称 "module.exports"
导出所需的值。
¥When an ES Module contains both named exports and a default export, the result returned by require()
is the module namespace object, which places the default export in the .default
property, similar to
the results returned by import()
.
To customize what should be returned by require(esm)
directly, the ES Module can export the
desired value using the string name "module.exports"
.
// point.mjs
export default class Point {
constructor(x, y) { this.x = x; this.y = y; }
}
// `distance` is lost to CommonJS consumers of this module, unless it's
// added to `Point` as a static property.
export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); }
export { Point as 'module.exports' }
const Point = require('./point.mjs');
console.log(Point); // [class Point]
// Named exports are lost when 'module.exports' is used
const { distance } = require('./point.mjs');
console.log(distance); // undefined
请注意,在上面的示例中,当使用 module.exports
导出名称时,命名导出将丢失给 CommonJS 消费者。为了允许 CommonJS 消费者继续访问命名导出,模块可以确保默认导出是一个对象,其中命名导出作为属性附加到它。例如,对于上面的例子,distance
可以作为静态方法附加到默认导出 Point
类。
¥Notice in the example above, when the module.exports
export name is used, named exports
will be lost to CommonJS consumers. To allow CommonJS consumers to continue accessing
named exports, the module can make sure that the default export is an object with the
named exports attached to it as properties. For example with the example above,
distance
can be attached to the default export, the Point
class, as a static method.
export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); }
export default class Point {
constructor(x, y) { this.x = x; this.y = y; }
static distance = distance;
}
export { Point as 'module.exports' }
const Point = require('./point.mjs');
console.log(Point); // [class Point]
const { distance } = require('./point.mjs');
console.log(distance); // [Function: distance]
如果 require()
的模块包含顶层 await
,或者 import
的模块图包含顶层 await
,则将抛出 ERR_REQUIRE_ASYNC_MODULE
。在这种情况下,用户应该使用 import()
加载异步模块。
¥If the module being require()
'd contains top-level await
, or the module
graph it import
s contains top-level await
,
ERR_REQUIRE_ASYNC_MODULE
will be thrown. In this case, users should
load the asynchronous module using import()
.
如果启用了 --experimental-print-required-tla
,Node.js 将评估模块,尝试找到顶层等待,并打印其位置以帮助用户修复它们,而不是在评估之前抛出 ERR_REQUIRE_ASYNC_MODULE
。
¥If --experimental-print-required-tla
is enabled, instead of throwing
ERR_REQUIRE_ASYNC_MODULE
before evaluation, Node.js will evaluate the
module, try to locate the top-level awaits, and print their location to
help users fix them.
使用 require()
加载 ES 模块的支持目前处于实验阶段,可以使用 --no-experimental-require-module
禁用。要打印使用此功能的位置,请使用 --trace-require-module
。
¥Support for loading ES modules using require()
is currently
experimental and can be disabled using --no-experimental-require-module
.
To print where this feature is used, use --trace-require-module
.
可以通过检查 process.features.require_module
是否为 true
来检测此功能。
¥This feature can be detected by checking if
process.features.require_module
is true
.