VSCode调试Hono项目必须用tsx启动,因其依赖JSX/TSX语法、顶层await及ESM特性,直接node运行会报Cannot use import statement outside a module或Unexpected token '

VSCode 能直接运行 .mjs 文件,但必须满足两个硬性条件:Node.js ≥ 12.0.0,且文件被明确识别为 ESM —— 否则会报 SyntaxError: Cannot use import statement outside a module。
为什么 node index.mjs 成功,但 VSCode 调试器报错?
VSCode 的调试器(launch.json)默认按 CommonJS 模式启动,即使文件后缀是 .mjs,它仍可能忽略 ESM 规则,尤其在旧版 VSCode(
- 确认 Node.js 版本:
node -v必须 ≥ 14(推荐 ≥ 18),否则--inspect协议不兼容 ESM 调试 -
launch.json中不能手动加--loader或--input-type=module—— 这会和 VSCode 自动注入的调试参数冲突 - 正确写法是让 VSCode 基于文件扩展名自动识别:
"program": "${workspaceFolder}/index.mjs",且确保该路径真实存在、无拼写错误 - 如果断点变灰,检查
type字段是否误设为chrome或pwa-node;ESM 调试必须用"type": "node"
package.json 里 "type": "module" 和 .mjs 同时存在会怎样?
两者不冲突,但优先级不同:.mjs 后缀具有最高优先级,Node.js 会无视 package.json 的 type 字段,强制按 ESM 解析;而 .js 文件才真正依赖 type 字段。
根据 package.json 中的 engines 字段自动检测 Node.js 版本需求,未安装 nvm 时自动安装并切换至对应版本。支持 Windows、macOS、Linux。适用于 Node.js 项目开发、版本切换和环境配置。
- 混用时常见陷阱:项目里既有
index.mjs又有utils.js,后者若用了import但没配"type": "module",就会报错 - 建议统一策略:全用
.mjs就删掉type字段;想保留.js扩展名,就只靠package.json控制,别混用 -
require()在 ESM 环境下不可用,哪怕在.mjs里调用也会报ReferenceError: require is not defined
终端里 node index.mjs 正常,但 F5 调试失败的典型原因
F5 启动的是调试协议(--inspect),不是普通执行;它对模块解析路径、工作目录、甚至 Node.js 内部 loader 链路更敏感。
-
cwd字段缺失或错误:如果launch.json没设"cwd": "${workspaceFolder}",Node.js 可能从 VSCode 安装目录启动,导致import的相对路径全部失效 - 路径含空格或中文:VSCode 通常能自动处理,但某些旧版本对
.mjs的路径解析仍有 bug,临时解法是把项目移到纯英文无空格路径(如/tmp/myapp) - 用了
nodemon并直接改了runtimeExecutable:这会让 VSCode 无法注入调试参数,应改用runtimeArgs+runtimeExecutable组合,且runtimeArgs里不要重复写--inspect - VSCode 缓存问题:修改
launch.json后未重启调试会话,或之前断点残留导致状态错乱;可尝试关闭所有窗口,重新打开文件夹再试
真正卡住的地方往往不是语法,而是 Node.js 对 ESM 的路径解析规则和 VSCode 调试器对 --inspect 参数的接管方式——这两者稍有错位,import 就会找不到模块,断点就永远灰着。动手前先跑通 node index.mjs,再配 launch.json,比反过来排查快得多。

















