节点 --experimental-modules - 错误:找不到模块
Posted
技术标签:
【中文标题】节点 --experimental-modules - 错误:找不到模块【英文标题】:Node --experimental-modules - Error: Cannot find module 【发布时间】:2019-11-05 11:59:26 【问题描述】:尝试导入本地文件时出现错误,但使用 npm 包时没有问题。
server.js
import express from 'express'
import next from 'next'
import apis from './src/server/api'
api.js
export default
ello: 'bye',
jamie: 'hey'
启动应用程序
node --experimental-modules --inspect server.js
错误
For help, see: https://nodejs.org/en/docs/inspector
(node:20153) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find module '/var/www/goldendemon.hutber.com/src/server/api' imported from /var/www/goldendemon.hutber.com/server.js
at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
at Loader.resolve (internal/modules/esm/loader.js:70:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:143:40)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
at link (internal/modules/esm/module_job.js:42:36)
code: 'ERR_MODULE_NOT_FOUND'
【问题讨论】:
【参考方案1】:或者像我一样,在你的源代码处理 ES 样式模块导入或其他一些非标准 javascript 代码(例如 TypeScript)在 Node.js 上的那一刻使用转译。作为参考,请参阅我编写的这个快速 bash 脚本,在我的 Node 项目中另存为 .script/run-it.sh
:
#!/bin/bash
script=$1
out_path==/tmp/$script-out.js
npx esbuild --platform=node --bundle --outfile=$out_path $script
node $out_path
我将它作为运行脚本添加到我的package.json
:
"scripts":
"test": "sst test",
"start": "sst start",
"build": "sst build",
"deploy": "sst deploy",
"remove": "sst remove",
"run-it": "./.script/run-it.sh"
,
还有我的目标脚本 (import-test.js
),我想作为 JavaScript 代码发出/转译:
import default as myImport from './lib/index.js'
console.log(myImport)
现在我运行它:
$ npm run run-it ./import-test.js
> my-nop@0.1.0 run-it /Users/jmquij0106/git/a-rebalancing-act
> ./.script/run-it.sh "./import-test.js"
[Function: main]
无论何时在 Node.js 上处理 ES 模块,底线都会让您免于痛苦,只需发出符合 CommonJS 的代码,请参阅 this comment/issue。
【讨论】:
【参考方案2】:如果其他人有这个问题,我正在回答我自己的问题。
事实证明,在实验模式下,您需要定义带有扩展名的完整路径。所以我尝试导入index.js
认为它会知道。
修复它:
import express from 'express'
import next from 'next'
import api from './src/server/api/index.js'
【讨论】:
天哪,这是具有挑战性的......添加.js
扩展是让我受不了的原因。您的回答有助于诊断!
你如何使用 typescript 进行这项工作?当我运行tsc
时,我的文件是使用不带扩展名的导入编译的。
对于 TypeScript(使用 Node 12),请参阅 Mateus 的回答 (#answer-57558982)。在使用 node
运行脚本时使用此 (--es-module-specifier-resolution=node
) 选项将解决问题,但您可能会遇到其他小问题(例如,__dirname
未定义)。
我认为 Node 实验模式太麻烦了,不能只运行一个简单的测试脚本来处理 ESM 样式的导入,所以我只好转而使用 esbuild
。我写了这个简短的 bash 脚本来完成这个:#!/bin/bash script=$1 out_path==/tmp/$script-out.js npx esbuild --platform=node --bundle --outfile=$out_path $script node $out_path
嘿,不确定它是否能解决您的问题,但试一试。检查这个Github comment 和这个Node Docs。总结一下,可以把"#api": "./src/server/api/index.js"
加到你的package.json["imports"]
里面,导入可以用import api from '#api'
解决【参考方案3】:
在节点 12 上,您有 2 个选项:
在 package.json、实验模块上使用 type="module" 并指定具有特定分辨率的扩展,如下所示:
node --experimental-modules --es-module-specifier-resolution=node src/index
或不使用说明符分辨率。请记住,您必须在每个位置指定文件的扩展名。
【讨论】:
请注意,尚不清楚--es-module-specifier-resolution
是否会继续存在。这也意味着代码与其他 ES 模块运行时(例如浏览器)不兼容。
已转换为:--experimental-specifier-resolution=node
看到 here (careful, theres a typo in that post)【参考方案4】:
如果您使用 .mjs
扩展名命名模块文件,它也应该可以工作。此外,还提到了启用 ESM 的其他方法here。
当 Node.js 作为初始输入传递给 node 或被 ES 模块代码中的 import 语句引用时,Node.js 会将以下内容视为 ES 模块:
以 .mjs 结尾的文件。
以 .js 结尾的文件或无扩展名文件,当最近的父 package.json 文件包含一个值为“module”的***字段“type”时。
作为参数传入 --eval 或 --print 的字符串,或通过 STDIN 管道传输到节点,带有标志 --input-type=module。
【讨论】:
以上是关于节点 --experimental-modules - 错误:找不到模块的主要内容,如果未能解决你的问题,请参考以下文章
节点 --experimental-modules,请求的模块不提供名为的导出
如何在 Typescript 输出中使用 node --experimental-modules