节点 --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
尚不支持命名导出:
https://github.com/apollographql/graphql-tools/issues/913--experimental-modules 不支持从 commonjs 模块导入命名导出(node 自己的内置模块除外)。
这就是您无法使用语法的原因:
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