[英]Unable to import ESM module in Nestjs
我在基於 Nest.js 的項目中導入 ESM 模塊時遇到問題。 據我了解,這個問題不僅與 Nest.js 相關,還與 typescript 相關。
我嘗試了 Node.js 和 typescript 版本的各種組合,將"type":"module"
添加到package.json
並更改了我的tsconfig.json
文件的設置,因此它具有以下視圖,與默認值相去甚遠:
{
"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,
}
}
我的完整環境是:
但是當我嘗試在我的任何服務中導入任何 ESM 模塊時,它仍然給我一個錯誤。 例如:
import random from `random`;
export class AppService implements OnApplicationBootstrap {
async test() {
const r = random.int(1, 5);
console.log(r);
}
}
有誰知道如何解決它?
這個問題似乎更頻繁地發生,因為更多的包正在切換為作為 ES 模塊分發。
概括
這個問題有兩種方法。
import()
異步導入 package function CommonJS 中 ES 模塊使用import()
的說明隨處可見。 但是當使用 typescript 時,附加提示丟失了如何防止編譯器將import()
調用轉換為require()
。 我為此找到了兩個選擇:
tsconfig.json
(變體 1)中將nodenext
moduleResolution
node16
eval
解決方法 - 這基於答案https://stackoverflow.com/a/70546326/13839825 (變體 2 和 3)中的“解決方案 2:使用 eval 的解決方法”部分await import()
這個解決方案在 NestJS 官方Discord上也經常出現
"moduleResolution": "nodenext"
或"moduleResolution": "node16"
添加到您的tsconfig.json
await import()
調用async
上下文import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
async getHello(): Promise<string> {
const random = (await import('random')).default;
return 'Hello World! ' + random.int(1, 10);
}
}
注意:從 ES 模塊導入類型不會導致require
調用,因為它僅由 typescript 編譯器而不是運行時環境使用。
async
上下文import { Injectable } from '@nestjs/common';
import { type Random } from 'random';
async function getRandom(): Promise<Random> {
const module = await (eval(`import('random')`) as Promise<any>);
return module.default;
}
@Injectable()
export class AppService {
async getHello(): Promise<string> {
return 'Hello World! ' + (await getRandom()).int(1, 10);
}
}
import { Injectable } from '@nestjs/common';
import { type Random } from 'random';
let random: Random;
eval(`import('random')`).then((module) => {
random = module.default;
});
@Injectable()
export class AppService {
async getHello(): Promise<string> {
return 'Hello World! ' + random.int(1, 10);
}
}
盡管不受支持,但似乎可以將 NestJS 設置為編譯為 ESM。 本指南有很好的一般說明,可以在 typescript 項目中執行此操作。
我用 NestJS 測試了它,發現這些步驟足夠了:
"type": "module"
到你的package.json
NodeNext
的 compilerOptions 中將module
更改為tsconfig.json
.js
擴展名添加到所有相關導入現在導入應該按預期工作
import { Injectable } from '@nestjs/common';
import random from 'random';
@Injectable()
export class AppService {
async getHello(): Promise<string> {
return 'Hello World! ' + random.int(1, 10);
}
}
到目前為止沒有用的是開玩笑的單元測試。 我在那里遇到了其他導入錯誤,我敢打賭未來還會有更多問題。 我會避免這種方法,等到 NestJS 正式支持 ES 模塊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.