如何在Node 8的Node.js REPL中导入ES模块?
如何在Node 8的Node.js REPL中导入ES模块?
我有一个 ES6 模块 right.mjs。将其作为参数传递给 node 执行可以正常工作:
$ node --version
v8.10.0
$ node --experimental-modules right.mjs
(node:4492) ExperimentalWarning: The ESM module loader is experimental.
执行 right 模块
`执行 right 模块` 是该模块的输出。
相比之下,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)
那么,我如何在 Node.js REPL 中导入一个 ES 模块呢?
在Node.js的REPL中,我们想要导入一个ES模块,但是在Node 8版本中,这是不可能的。然而,在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 {} > myModule.foo(); "bar"
这段代码展示了如何在Node.js的REPL中导入一个ES模块。我们首先声明了一个变量myModule
,然后使用import
函数来导入my-module.js
模块,并将其赋值给myModule
变量。接着,我们可以通过myModule.foo()
来访问模块的方法或属性。
然而,这种方法似乎无法处理包含export
关键字的模块。如果你的模块中包含export
关键字,你需要通过module.default
来访问默认导出。
另外,如果你的文件中的导入语句没有指定文件扩展名(比如import something from './something';
),那么会报错。目前还没有找到解决这个问题的方法。
然而,对于异步导入的问题,可以使用node --experimental-repl-await
命令来解决。在导入模块时,可以使用await
关键字来等待导入完成,比如const myModule = await import("./my-module.js")
。此外,还可以使用--experimental-specifier-resolution=node
参数来省略文件扩展名,或者使用自定义加载器(--experimental-loader
)来解决这个问题。
,虽然在Node 8版本中无法直接在REPL中导入ES模块,但是在Node.js v14版本中,可以通过使用import
函数来实现。然而,如果模块中包含export
关键字,需要通过module.default
来访问默认导出。目前还没有找到解决文件扩展名问题的方法。对于异步导入的问题,可以使用node --experimental-repl-await
命令以及--experimental-specifier-resolution=node
参数来解决。
问题的原因是,ES模块应该从ES模块范围中导入,而REPL并不被认为是一个ES模块范围。这是因为ES模块的支持是实验性的,随着时间的推移,这种情况可能会改善。在Node.js模块实现中,使用require和import是互斥的,而REPL已经使用了require。从Node.js 13开始,REPL中支持动态导入(import)。通过使用node --experimental-repl-await
命令,可以实现动态导入。在Node 16.6中,默认情况下REPL await已经打开,并且有不同的语法。在Node 18中,let { date } = await import('quasar')
可以正常工作,无需任何标志。但是需要注意的是,这不是一个静态导入,因此并不能算是“正常工作”。可以看出,REPL在某种异步包装器的CJS模式下运行。考虑到REPL主要用于检查同步代码,这可能会导致不同的意外运行时行为。因此,当前的Node.js REPL无法在Node 8中导入ES模块的解决方法是使用Node.js 13及以上版本,并使用node --experimental-repl-await
命令来启用动态导入(import)功能。