编译后TypeScript代码运行报错:Cannot find module 求解
问题描述
我的tsconfig.json配置如下:
{ "compilerOptions": { "target": "es2016", "lib": ["es6"], "module": "commonjs", "rootDir": "./", "baseUrl": "./", "resolveJsonModule": true, "allowJs": true, "outDir": "build", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": false, "noImplicitAny": false, "skipLibCheck": true }, "ts-node": { "swc": true } }
我通过baseUrl在代码中使用相对导入,执行tsc -p .编译代码无问题,但运行NODE_PATH=./build node ./build/app.js时出现错误:
Error: Cannot find module '<PROJECT_FOLDER_NAME>/app/listeners/module.ts' Require stack: { code: 'MODULE_NOT_FOUND', requireStack: [ '<PROJECT_FOLDER_NAME>/bot/build/app/listeners.js', '<PROJECT_FOLDER_NAME>/bot/build/app.js' ] }
代码逻辑是在listeners.js中循环读取app/listeners目录下的所有文件,并调用模块的默认导出函数,但程序始终在原app目录下查找TypeScript模块,而非build/app下的编译后JS文件。
目录结构如下:
. ├── app.ts ├── tsconfig.json └── app ├── registerListeners.ts ├── listeners │ └── actions │ └── edit.ts ├── views └── modals
解决方法
1. 修正动态导入的路径指向
问题核心是动态读取文件时,使用了项目根目录下的原TS文件路径,而非编译后build目录下的JS文件路径。
- 若用
fs.readdir类API读取目录,要确保目标路径是build/app/listeners,而非原app/listeners - 导入模块时,需去掉
.ts后缀,改用.js或直接省略后缀(Node.js会自动匹配对应JS文件)
示例修正代码:
// 原错误写法(示例) const files = fs.readdirSync('./app/listeners/actions'); files.forEach(file => { require(`../app/listeners/actions/${file}`); // 指向原TS目录且未处理后缀 }); // 修正后 const listenerDir = path.join(__dirname, './listeners/actions'); const files = fs.readdirSync(listenerDir); files.forEach(file => { // 只导入编译后的JS文件 if (file.endsWith('.js')) { require(path.join(listenerDir, file)); } });
2. 调整tsconfig.json的rootDir配置
当前rootDir: "./"会把根目录下所有TS文件编译到build目录对应位置,易导致路径解析混乱。建议将rootDir指定为源码目录:
"rootDir": "./app",
同时通过include字段明确编译范围:
"include": ["./app/**/*", "./app.ts"]
3. 移除不必要的NODE_PATH设置
NODE_PATH=./build会干扰Node.js的模块解析逻辑,编译后的文件已在build目录下,直接运行node ./build/app.js即可,无需额外配置NODE_PATH。
4. 动态导入优先用相对路径
避免使用基于项目根目录的绝对路径导入,改用相对于当前文件的相对路径(比如./actions/edit而非/app/listeners/actions/edit),编译后路径会自动对应到build目录下的正确位置。
内容的提问来源于stack exchange,提问作者Élodie Petit
相关产品推荐
相关产品推荐

