如何在 Node.js REPL 中导入 ES 模块?

Posted

技术标签:

【中文标题】如何在 Node.js REPL 中导入 ES 模块?【英文标题】:How can I import an ES module in the Node.js REPL? 【发布时间】:2019-07-14 00:58:29 【问题描述】:

我有一个ES6 模块right.mjs。将其作为node 的参数执行效果很好:

$ node --version
v8.10.0

$ node --experimental-modules right.mjs
(node:4492) ExperimentalWarning: The ESM module loader is experimental.
executing right module
`executing right module` is the output of the module.

与此相反,REPL 中的以下输入等待进一步的输入:

$ node --experimental-modules
> (node:4526) ExperimentalWarning: The ESM module loader is experimental.

> import 'right.mjs';
...

我不明白为什么。

同理:

> import './right.mjs';
...

尝试require 会导致:

> require('./right.mjs');
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/xxx/right.mjs
    at Object.Module._extensions..mjs (module.js:686:11)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)

那么,

【问题讨论】:

【参考方案1】:

在 Node.js v14 中可以,但您需要使用 import 函数,而不是 import 语句。

$ node

Welcome to Node.js v14.4.0.
Type ".help" for more information.
> let myModule;
undefined
> import("./my-module.js").then(module =>  myModule = module );
Promise  <pending> 
> myModule.foo();
"bar"

【讨论】:

:( 看起来它仍然无法处理包含 export 关键字的模块 @hallo 它适用于我的命名导出和默认导出,但请记住,您必须在 module.default 访问默认导出。 不幸的是,如果您的文件包含文件名中没有扩展名的导入(`import something from './something';),就像大多数项目一样,它会出错。有没有办法解决这个问题? 扩展现在是强制性的:nodejs.org/api/esm.html#esm_mandatory_file_extensions - 我不知道有什么办法。 node --experimental-repl-await解决了异步导入的问题。然后是const myModule = await import("./my-module.js")。可以使用 --experimental-specifier-resolution=node 或自定义加载程序 (--experimental-loader) 省略扩展。【参考方案2】:

This is not currently possible。 ES 模块应该是从 ES 模块范围导入的,而 REPL 不被认为是一个。这可以随着时间的推移而改善,因为对 ES 模块的支持是实验性的。 requireimport的使用在Node.js模块实现中是互斥的,REPL已经使用了require

自 Node.js 13 起,REPL 支持动态 import。使用 node --experimental-repl-await,它是:

await import('./right.mjs');

【讨论】:

我相信现在正在github.com/nodejs/node/issues/33369中进行跟踪 从 Node 16.6 开始,REPL 等待默认开启,并且功能标志为 a different syntax。【参考方案3】:

这并不是所问的(不是真正的 REPL),而是(使用 Node.js 12.6.0),可以通过--eval 从命令行执行 ESM 代码:

    首先,如果您的 ES 模块具有 .js 扩展名而不是 .mjs,请将 "type": "module" 放在文件 package.json 中(请参阅 Modules: ECMAScript modules, Enabling) 以允许 Node.js 将 javascript 文件视为模块 运行node --experimental-modules --input-type=module --eval 'code here'

您可以将其别名为 esmeval,例如:

alias esmeval='node --experimental-modules --input-type=module --eval'

然后您可以将其用作:

esmeval 'import method from "./path/to/utils.js"; console.log(method("param"))'

如果您还不能使用 Node.js 12 作为主要版本,但可以通过 nvm 安装,请将别名指向 v12 安装:

alias esmeval='/c/software/nvm/v12.6.0/node.exe --experimental-modules --input-type=module --eval'

【讨论】:

请注意,ES 模块的实现随着节点 13 的变化而变化,因此这可能不适用于较新版本的节点。【参考方案4】:

使用支持*** await 的 Node.js v16.9.1,它更加简单:

let  date  = await import('quasar') // module under node_modules, or your own one, etc.
date.getWeekOfYear(new Date())

【讨论】:

以上是关于如何在 Node.js REPL 中导入 ES 模块?的主要内容,如果未能解决你的问题,请参考以下文章

在 Node.js 中导入:错误“必须使用导入来加载 ES 模块”[重复]

在 ES 模块(Node.js)中导入 JSON 文件

如何在 node.js 中导入 font-awesome 以在 react.js 中使用?

无法在 node.js 中导入模块 [重复]

在 node.js 中导入 sql 文件并针对 PostgreSQL 执行

如何使用 npm 在 ES6 中导入 moment.js?