NodeJS机器人开发:加载命令目录子目录时ESM错误修复
问题:Node.js ESM 导入本地文件触发 ERR_UNSUPPORTED_ESM_URL_SCHEME 错误
我正在用Node.js开发机器人,想做一个帮助命令,命令文件按分类放在commands/slash目录的子文件夹(比如Moderation)里。当前代码如下:
import Command from "../../../structures/Command.js" import { Embed } from "eris-addons" import fs from "fs" import { readdirSync } from "fs" import path from "path" import { join } from "path" import { fileURLToPath } from "url" const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Map of category names to command objects const categories = new Map(); // Load commands from the "commands/slash" folder and its subdirectories const commandFolders = readdirSync(path.join(__dirname, '../')); for (const folder of commandFolders) { const fullPath = path.join(__dirname, '../', folder); if (fs.lstatSync(fullPath).isDirectory()) { const commandFiles = fs.readdirSync(fullPath).filter((file) => file.endsWith('.js')); for (const file of commandFiles) { const filePath = path.join(fullPath, file); const { default: CommandClass } = await import(filePath); const command = new CommandClass(); if (!categories.has(folder)) { categories.set(folder, []); } categories.get(folder).push(command); } } }
运行时出现以下错误:
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
错误来自const { default: CommandClass } = await import(filePath);这一行,请问如何修复?
解决方案
错误原因
ESM模块规范中,import()函数仅支持file:// 协议的URL或data URL。在Windows系统中,直接传入的本地绝对路径(如C:\xxx\command.js)会被Node.js误判为c:协议,不符合ESM导入要求,因此触发错误。
修复步骤
- 从
url模块导入pathToFileURL方法,它可以将本地文件路径转换为合法的file:// URL。 - 修改导入语句,用
pathToFileURL处理本地路径后再传入import()。
修改后的关键代码:
首先更新顶部的导入:
import { fileURLToPath, pathToFileURL } from "url"
然后替换原导入语句:
// 替换原有的 import(filePath) 行 const { default: CommandClass } = await import(pathToFileURL(filePath));
说明
pathToFileURL会自动适配系统路径格式:
- 在Windows下,将
C:\project\commands\slash\Moderation\kick.js转换为file:///C:/project/commands/slash/Moderation/kick.js - 在类Unix系统下,将
/home/user/project/commands/slash/Moderation/kick.js转换为file:///home/user/project/commands/slash/Moderation/kick.js
完全符合ESM导入的URL要求。
内容的提问来源于stack exchange,提问作者ETLegacy
相关产品推荐
相关产品推荐

