使用ts-node加载ESM模块失败报错无法找到模块,请求技术排查
核心问题所在
在ESM模块规范下,Node.js(包括处理ESM的ts-node)要求所有相对路径的导入必须带上完整的文件扩展名,这和你之前用的CommonJS模式差异很大——CommonJS允许Node自动补全.js这类扩展名,但ESM为了规范和性能砍掉了这个特性。你在index.ts里写的import { SmokeTest } from "./SmokeTest";没有指定.ts扩展名,这就是报错的直接原因。
具体修复步骤
修正导入语句的扩展名
把index.ts里的导入代码改成下面这样,加上.ts后缀:import { SmokeTest } from "./SmokeTest.ts"; SmokeTest.Log();不用担心编译后的扩展名问题,ts-node在处理ESM时会自动完成从
.ts到.js的转换。确保ts-node的ESM模式完全生效
你的tsconfig.json和package.json配置已经基本正确,不过运行命令时可以显式加上--esm参数(和配置文件里的"esm": true互为补充,避免环境差异导致的问题):./node_modules/.bin/ts-node --esm index.ts可选优化:调整导出方式(更贴合ESM规范)
你当前的SmokeTest.ts用了TypeScript的module语法,虽然能正常工作,但ESM更推荐直接导出的写法,代码会更简洁:export function Log(){ console.log("Smoke test running"); }对应的导入也可以简化成:
import { Log } from "./SmokeTest.ts"; Log();当然,如果习惯保留模块结构,原写法也没问题,只要补上扩展名就能正常运行。
补充说明
之前CommonJS模式能正常运行,是因为Node.js会自动尝试为省略扩展名的导入补全.js、.json,甚至去查找目录下的index.js;但ESM为了统一模块解析规则、提升加载性能,强制要求必须明确指定文件扩展名,这是你切换模式后踩坑的关键原因。
内容的提问来源于stack exchange,提问作者sanjihan

