我在基于Nest.js的项目中导入ESM模块时遇到了一个问题。据我所知,这个问题不仅与Nest.js有关,还与typescript有关。
我尝试了Node.js和typescript版本的各种组合,将"type":"module"
添加到package.json
中,并更改了tsconfig.json
文件的设置,因此它具有以下视图,与 default 值相差甚远:
{
"compilerOptions": {
"lib": ["ES2020"],
"esModuleInterop": true,
"module": "NodeNext",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "Node",
"target": "esnext",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
}
}
我的完整环境是:
- 通过nvm管理的Node.js(19.2.1 LTS)
- typescript (4.9.4,但我也尝试了4.3.5)
- @nestjs/常见:9.2.1
- @嵌套/内核:9.2.1
- ts-加载程序:“9.4.2”,
- TS节点:“10.9.1”,
- tsconfig路径:“4.1.0”,
但是当我尝试在我的任何服务中导入任何ESM模块时,它仍然会给我一个错误。
import random from `random`;
export class AppService implements OnApplicationBootstrap {
async test() {
const r = random.int(1, 5);
console.log(r);
}
}
有人知道怎么修吗?
1条答案
按热度按时间k10s72fa1#
由于更多程序包切换为作为ES模块分发,因此该问题似乎更频繁地发生。
解决这个问题有两种方法。
使用动态
import()
函数异步导入包在CommonJS中,为ES模块使用
import()
的指令随处可见。但是在使用typescript时,缺少了如何防止编译器将import()
调用转换为require()
的额外提示。我找到了两个选项:tsconfig.json
中将moduleResolution
设置为nodenext
或node16
(变体1)eval
解决方案-这基于"解决方案2:使用答案https://stackoverflow.com/a/70546326/13839825(变量2和3)中的eval "的解决方案变体1:
await import()
(根据需要)官方的NestJS Discord经常建议使用此解决方案
"moduleResolution": "nodenext"
或"moduleResolution": "node16"
添加到您的tsconfig.json
await import()
调用async
上下文中有效变体2:帮助函数
require
调用,因为它只被类型脚本编译器使用,而不是运行时环境。async
上下文中有效变体3:导入并保存到局部变量
将NestJS项目转换为ES模块(不推荐)
虽然不支持,但似乎可以设置NestJS以编译到ESM。This Guide有很好的说明,如何为任何类型脚本项目执行此操作。
我用NestJS测试了它,发现这些步骤足够了:
"type": "module"
添加到您的package.json
module
更改为NodeNext
tsconfig.json
中的选项.js
扩展添加到所有相关导入现在导入应该按预期工作。
到目前为止,用jest进行的单元测试没有起作用。我在那里得到了其他导入错误,我敢打赌以后还会有更多的问题。我会避免这种方法,直到NestJS正式支持ES模块。