Windows下Node.js ESM导入绝对路径报错:ERR_UNSUPPORTED_ESM_URL_SCHEME等
问题描述
我编写了一个Discord机器人,使用现代ES导入语法,package.json中配置了"type": "module"。在Linux系统上运行代码一切正常,但在相同Node.js版本(18.18.0)的Windows系统中出现错误。
原代码片段:
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:'
尝试多种修改均未解决:
- 给路径手动添加
file:前缀,触发ENOENT错误(路径实际存在但格式不被文件系统识别) - 混用
fileURLToPath和import,再次触发URL scheme不支持错误
解决方案
问题核心是Windows系统的绝对路径无法直接被ESM的import()识别,必须转换为标准的file://格式URL。正确做法是使用Node.js内置工具自动转换路径,而非手动拼接前缀。
修改后的代码:
import { dirname, join } from 'path'; import { fileURLToPath, pathToFileURL } from 'url'; const rootDir = dirname(fileURLToPath(import.meta.url)); const commandsPath = join(rootDir, 'src', 'commands'); const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.js')); for (const file of commandFiles) { const filePath = join(commandsPath, file); // 将本地文件路径转换为ESM可识别的file:// URL const fileUrl = pathToFileURL(filePath); const command = await import(fileUrl); console.log('SUCCESS'); // 后续逻辑... }
关键说明:
pathToFileURL()是Node.jsurl模块提供的方法,会自动处理Windows路径的格式问题,比如把C:\Users\...转换成合法的file:///C:/Users/...(注意三个斜杠的标准格式),完全符合ESM loader的要求。- 文件系统操作(如
readdirSync())仍使用普通系统路径即可,无需转换为URL,只有import()需要传入标准的file URL。
此修改可保证代码在Linux和Windows环境下均正常运行。
内容的提问来源于stack exchange,提问作者upcast
相关产品推荐
相关产品推荐

