在Windows节点js上使用绝对路径时获取ERR_UNSUPPORTED_ESM_URL_SCHEME或ENOENT或ERR_INVALID_URL_SCHEME

问题描述 投票:0回答:1

当我在 Linux 上运行我的代码时,它工作正常。但在具有相同 Node js 版本(18.18.0)的 Windows 上,我收到错误。

我使用现代 ES 导入,我的 package.json 有字符串

"type": "module"

我写了不和谐的机器人,这就是我所做的:

const rootDir = dirname(fileURLToPath(import.meta.url));
const commandsPath = join(rootDir, 'src', 'commands');
console.log('BEFORE FILTER');
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.js'));

console.log('BEFORE LOOP');
for (const file of commandFiles) {
    console.log('BEFORE JOIN');
    const filePath = join(commandsPath, file);
    console.log('BEFORE AWAIT');
    const command = await import(filePath);
    console.log('SUCCESS');
    // etc...

因此,如果我运行此代码,我会收到日志

BEFORE FILTER
BEFORE LOOP
BEFORE JOIN
BEFORE AWAIT
和错误

Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'

我尝试更改

commandsPath
初始化:

const commandsPath = join('file:', rootDir, 'src', 'commands');

运行时会出现日志

BEFORE FILTER
ENOENT 错误,命令目录的路径正确

Error: ENOENT: no such file or directory, scandir 'file:\C:\Users\Correct\Path\To\src\commands'

如果我尝试

const commandsPath = fileURLToPath(join('file:', rootDir, 'src', 'commands'));

BEFORE FILTER
BEFORE LOOP
BEFORE JOIN
BEFORE AWAIT
和第一个示例
ERR_UNSUPPORTED_ESM_URL_SCHEME
错误

最后,如果我尝试

const commandsPath = fileURLToPath(join('file:', rootDir, 'src', 'commands'));

const command = await import(fileURLToPath(filePath));

BEFORE FILTER
BEFORE LOOP
BEFORE JOIN
BEFORE AWAIT
TypeError [ERR_INVALID_URL_SCHEME]: The URL must be of scheme file

我该怎么办?

node.js windows absolute-path
1个回答
0
投票

提前道歉,我无法测试它,因为我不在Windows上运行,我根据知识给出答案,希望我是对的。

要解决此问题,您需要修复

'file:\C:\Users\Correct\Path\To\src\commands'
中的 URL。
致:
file:///C:/Users/Correct/Path/To/src/commands
.

有两个区别,一是 3

/
而不是 1,二是
''

这是 API 的一个非常愚蠢的行为,不知道自己删除
'
,虽然不那么愚蠢,但仍然是解决路径类型,但它就是这样。

要解决此问题,请使用

.href
并添加
\\
。在你最初的尝试中:


const rootDir = dirname(fileURLToPath(import.meta.url));
const commandsPath = join(rootDir, 'src', 'commands');
console.log('BEFORE FILTER');
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.js'));

console.log('BEFORE LOOP');
for (const file of commandFiles) {
    console.log('BEFORE JOIN');
    const filePath = join(commandsPath, file);
    console.log('BEFORE URL CONVERSION');
    const fileURL = new URL(`file://${filePath}`).href; // <- ** here **
    console.log('BEFORE AWAIT');
    const command = await import(fileURL);
    console.log('SUCCESS');
    // ... rest of your code
}

这次尝试

const commandsPath = join('file:', rootDir, 'src', 'commands');
应该是
const commandsPath = join('file:\\', rootDir, 'src', 'commands').href;

您也可以像这样添加
href
const command = await import(filePath.href);

© www.soinside.com 2019 - 2024. All rights reserved.