Node.js ESM模块动态导入文件失败,Node18/20表现异常
问题解决:CommonJS转ESM后readFileSync在Node18/20的路径兼容问题
问题根源
- ESM主模块中,Windows盘符开头的绝对路径(如
D:\xxx)会被Node识别为URL协议d:,触发ERR_UNSUPPORTED_ESM_URL_SCHEME错误。 - 转换为
file://字符串后,Node18的fs模块不支持直接处理该字符串格式;Node20则错误地将其作为相对路径拼接,导致路径混乱。 - 被导入的
parse.js能正常运行,是因为被导入模块的fs路径解析逻辑未触发ESM主模块的严格URL校验,直接使用resolve返回的本地路径即可正常工作。
解决方案
方案1:传递URL对象给readFileSync
直接使用pathToFileURL返回的URL对象,而非其字符串形式,Node18和20都能正确识别:
import { readFileSync } from 'fs'; import { resolve } from 'path'; import { pathToFileURL } from 'url'; const markdownPath = pathToFileURL(resolve(args.markdownPath)); console.log(`Loading existing file from '${chalk.blue(markdownPath.href)}'`); const markdownFileContent = readFileSync(markdownPath).toString();
方案2:将file:// URL转回本地路径
通过fileURLToPath将URL转换为平台兼容的本地绝对路径,和parse.js逻辑保持一致:
import { readFileSync } from 'fs'; import { resolve } from 'path'; import { pathToFileURL, fileURLToPath } from 'url'; const markdownPath = fileURLToPath(pathToFileURL(resolve(args.markdownPath))); console.log(`Loading existing file from '${chalk.blue(markdownPath)}'`); const markdownFileContent = readFileSync(markdownPath).toString();
方案3:直接使用resolve处理后的绝对路径
如果args.markdownPath是相对路径,resolve会自动转为绝对路径;如果是绝对路径,resolve也能确保Node正确识别为本地路径而非URL协议:
import { readFileSync } from 'fs'; import { resolve } from 'path'; const markdownPath = resolve(args.markdownPath); console.log(`Loading existing file from '${chalk.blue(markdownPath)}'`); const markdownFileContent = readFileSync(markdownPath).toString();
内容的提问来源于stack exchange,提问作者Roaders
相关产品推荐
相关产品推荐

