编译后TypeScript在Node.js 20中找不到导出模块的问题排查
问题解决:Node.js 20运行TypeScript编译后的ES模块提示模块未找到
问题背景
使用以下tsconfig.json编译TypeScript代码:
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] }
编译无报错,但运行node dist/server.js时出现模块未找到错误:
> node dist/server.js node:internal/modules/esm/resolve:255 throw new ERR_MODULE_NOT_FOUND( ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\Users\Documents\Development\AthletePT\dist\config\db' imported from C:\Users\Documents\Development\AthletePT\dist\server.js at finalizeResolution (node:internal/modules/esm/resolve:255:11) at moduleResolve (node:internal/modules/esm/resolve:908:10) at defaultResolve (node:internal/modules/esm/resolve:1121:11) at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12) at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25) at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38) at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39) at link (node:internal/modules/esm/module_job:84:36) { code: 'ERR_MODULE_NOT_FOUND', url: 'file:///C:/Users/Documents/Development/AthletePT/dist/config/db' } Node.js v20.10.0
确认db.js存在于dist/config目录且导出正常,Node.js 18中使用node --experimental-modules --es-module-specifier-resolution=node dist/server.js可正常运行,package.json已设置"type": "module"。
原因分析
Node.js对ES模块的解析规则在版本升级后更严格:
- ES模块规范要求导入路径必须包含完整文件扩展名(如
.js) - Node.js 18中
--es-module-specifier-resolution=node参数允许自动补全扩展名,但该参数在Node.js 20中默认关闭,且转为实验性参数 - 当前TypeScript编译配置下,生成的JS文件中导入路径不带扩展名,导致Node.js 20无法识别
解决方案
方案1:修改TypeScript编译配置,自动添加扩展名
更新tsconfig.json的compilerOptions,将module和moduleResolution改为NodeNext:
{ "compilerOptions": { "target": "ESNext", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] }
这样TypeScript会根据ES模块规范,自动在生成的JS文件的导入路径中添加.js扩展名,Node.js 20可正常解析。
方案2:手动在TypeScript代码中添加.js扩展名
在TS文件的导入语句中,手动加上目标JS文件的扩展名(即使源文件是.ts):
// 原导入:import db from './config/db' import db from './config/db.js'
编译后生成的JS文件会保留这个扩展名,Node.js可正确识别。
方案3:使用Node.js实验性参数临时解决(不推荐生产环境)
运行时添加--experimental-specifier-resolution=node参数,让Node.js自动补全扩展名:
node --experimental-specifier-resolution=node dist/server.js
注意:该参数为实验性功能,未来可能被移除,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者LetsGhost
相关产品推荐
相关产品推荐

