节点 --experimental-modules,请求的模块不提供名为的导出

Posted

技术标签:

【中文标题】节点 --experimental-modules,请求的模块不提供名为的导出【英文标题】:node --experimental-modules, requested module does not provide an export named 【发布时间】:2020-04-29 15:16:48 【问题描述】:

我已经安装了 Node 8.9.1(同样的问题发生在 v10.5.0 中)。

我正在尝试在带有.mjs 的文件中使用来自 npm 包的命名导入

import  throttle  from lodash;

我跑:

node --experimental-modules index.mjs

我得到:

语法错误:请求的模块“lodash”没有提供名为“throttle”的导出 在 ModuleJob._instantiate (internal/modules/esm/module_job.js:80:21)

--experimental-modules 应该是 stop being experimental in v10 LTS,那么为什么没有更多的模块作者加入这个潮流呢?

【问题讨论】:

ES6 imports in Node with --experimental-modules的可能重复 lodash-es 会解决它。 【参考方案1】:

编辑了新的(更好的)答案

Node 团队……很慢。与此同时,为我们带来 Lodash(John-David Dalton)的人设想了一个绝妙的解决方案,他的想法是在 2019 年获得完整 ES6 模块支持的最佳方式。

(事实上,我删除我之前的答案,但出于历史目的,我已将其保留。)

新的解决方案非常简单。

第 1 步:

npm i esm

(https://www.npmjs.com/package/esm了解包裹详情)

第 2 步:

node -r esm yourApp.js

这就是全部:真的就是这么简单。只需将 -r esm 添加为 Node arg,一切都会神奇地工作(它甚至比 --experimental-modules 更少打字!)谢谢你 John-David Dalton!!!

正如我在最初的回答中所说,大概有一天 Node 最终会发布完整的 ES6 支持,但是当发生这种情况时,采用它就像从几个脚本中删除“-r esm”一样简单: D

最后,为了给予应有的荣誉,虽然我没有通过他的回答找到它,但@Divyanshu Rawat 实际上早在我进行此更新之前就提供了这个库的前身的答案。

原始答案

--experimental-modules 尚不支持命名导出:

--experimental-modules 不支持从 commonjs 模块导入命名导出(node 自己的内置模块除外)。

https://github.com/apollographql/graphql-tools/issues/913

这就是您无法使用语法的原因:

 import  throttle  from 'lodash';

相反(至少现在)你必须破坏你需要的东西:

 import lodash from 'lodash';
 const  throttle  = lodash;

大概有一天 Node 会添加对所有 ES 模块功能的支持。

【讨论】:

我不同意这个答案中的第一句话。 @stackdave 的 import throttle from lodash; 将在 lodash 被编写为模块时工作,即 lodash/index.mjs 像这样导出油门 export const throttle = ...; 我不明白你不同意什么:Lodash 是按照它的编写方式编写的。您关于 lodash 以其他方式编写的假设性谈话不会使答案无效。 还是这样吗? ESM 会直接支持命名导出吗? 我只是补充一点,如果你想在 Typescript 中使用严格模式的语法,你应该启用“allowSyntheticDefaultImports”编译器选项 遗憾的是,对于 Node.js > v12.12.0(包括所有 Node.js 13 和 Node.js 14),这个包不起作用。这个问题已经打开了几个月,所以我对这个包的期望不高。问题链接:https://github.com/standard-things/esm/issues/868【参考方案2】:

您必须使用.mjs 扩展名。

设置完成后,以 .mjs 结尾的文件将能够作为 ES 模块加载。

参考:https://nodejs.org/api/esm.html

更新:

看起来你还没有导出方法。

假设我有 hello.mjs 的内容

export function sayHello() 
    console.log('hello')

我可以像这样在index.mjs 中使用它

import sayHello from './hello.mjs'
sayHello()

【讨论】:

谢谢我用一个新的错误更新了我的答案,很抱歉我的答案是能够使用节点 8 运行模块 已更新。如果你能发布你的代码内容就更好了 我已经意识到在整个项目中使用模块导入的所有文件都必须具有 .mts 扩展名。请参阅我的答案的更新。 OP 询问是否从 npm 模块导入,而不是他们自己的。【参考方案3】:

对我来说,加载 lodash 是因为 ES 库 完成了这项工作,这里是同样的 NPM 包

Lodash 库导出为 ES 模块。 https://www.npmjs.com/package/lodash-es

然后就可以正常导入utils了。

import  shuffle  from 'lodash-es';

【讨论】:

我刚刚添加了对我有帮助的内容,有人否决了它,任何人都可以解释。 我不知道为什么这最初被否决了;也许你解释得不够好?如果有什么安慰的话,我实际上已经更新了我的(接受的)答案,提到了 esm 模块,我相信它是你提到的那个模块的继承者(FWIW 我赞成你的答案)。【参考方案4】:

我刚刚在 nodejs express *.mjs 文件和为 googleapis 启用 --experimental-modules 标志时遇到了这个错误。

从“googleapis”导入 google ;

语法错误:请求的模块“googleapis”未提供名为“google”的导出

解决方案

//not working!
//import  google  from "googleapis";

//working
import googleapis from "googleapis";
const  google  = googleapis;

我不明白为什么会这样;如果有人知道原因,请发表评论。

【讨论】:

这是因为 ESM 模块具有“命名导出”的自定义概念,而不仅仅是使用解构导出对象和导入语句。【参考方案5】:

如果 lodash 被编写为模块,并且 lodash/index.mjs 导出 throttle: export const throttle = ...;,那么您将能够 import throttle from lodash;

这里的问题是,在 commonjs 中没有命名导出之类的东西。这意味着在 commonjs 模块中只导出一件事。

所以认为 lodash 导出的对象包含一个名为 throttle 的属性。

对于问题的第二部分,我相信一旦不再是实验性的 ES 模块,人们就会慢慢开始采用它。在撰写本文时,它仍然是 (Node.js v11.14)。

【讨论】:

【参考方案6】:

@machineghost 答案有效。我记得还添加了'type':'module' 到 package.json 以及将 esm 与 node v12(LTS) 一起使用,它工作正常。## Heading ##

我将节点更新为 v14(当前),但出现错误

C:\Users\andey\Documents\Project\src\app.js:1
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: 
C:\Users\andey\Documents\Project\src\app.js
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1217:13) 
code: 'ERR_REQUIRE_ESM'

要修复它,我必须从 package.json 中删除 'type':'module'

source

【讨论】:

以上是关于节点 --experimental-modules,请求的模块不提供名为的导出的主要内容,如果未能解决你的问题,请参考以下文章

节点 --experimental-modules,请求的模块不提供名为的导出

如何在 Typescript 输出中使用 node --experimental-modules

nodejs12 支持es6模块加载

Node.js 宣布正式支持 ECMAScript modules

Nodejs中ES Modules如何操作运用?本文详解

Node.js 8.5 带来哪些新特性