Nest.js配置使用ES2022兼容ES模块包时出现模块找不到错误,该如何解决?
这个错误我之前也碰到过!其实核心原因是Node.js的ES模块(ESM)规则要求所有导入必须带完整的文件扩展名,比如.js,但你当前的TypeScript配置和代码导入方式没跟上这个规则,导致Node.js找不到实际存在的编译后文件(比如你导入的是app.module,但编译后实际生成的是app.module.js,Node.js就会因为找不到app.module这个文件而报错)。
下面是一步步的解决方法,亲测有效:
1. 修正TypeScript的模块解析策略
打开你的tsconfig.json,把moduleResolution从bundler改成node16或者nodenext——这两个选项是专门为Node.js的ESM规则设计的,能让TypeScript生成符合Node.js要求的导入语句:
{ "compilerOptions": { "module": "ES2022", "moduleResolution": "node16", // 替换原来的bundler "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, "target": "ES2022", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "incremental": true, "skipLibCheck": true, "strictNullChecks": false, "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false, "esModuleInterop": true, "lib": ["ES2022"], "resolveJsonModule": true // 可选,如果你需要导入JSON文件的话 }, "exclude": ["node_modules"], "include": ["src/**/*.ts", "bin/*.ts"] }
2. 给代码里的导入语句补上扩展名
在你的TypeScript代码中,哪怕是导入.ts文件,也要写成编译后的.js扩展名。比如main.ts里的导入:
原来的写法:
import { AppModule } from './app.module';
改成:
import { AppModule } from './app.module.js';
别担心,TypeScript会自动把这个映射到对应的.ts源文件,编译后生成的代码就会带着正确的.js扩展名,Node.js就能找到文件了。
3. 调整启动脚本适配ESM
在package.json里,把启动脚本改成使用支持ESM的运行方式,比如用ts-node-esm:
"scripts": { "start": "ts-node-esm src/main.ts", "start:dev": "nest start --watch --exec ts-node-esm", "start:prod": "node dist/src/main.js" }
这样Nest CLI和ts-node就能以ESM模式正确运行你的代码了。
4. 清理旧编译文件重新启动
最后,删掉dist目录(避免旧的编译文件搞事情),然后重新启动:
# Windows用户可以手动删除dist文件夹,或者用: rmdir /s dist # 然后启动开发模式 npm run start:dev
如果还是有问题,再检查下package.json里的"type": "module"有没有写错(比如引号是不是中文的),还有所有导入的相对路径有没有拼写错误,一般这几步就能解决问题啦!
备注:内容来源于stack exchange,提问作者CodeGhinux

