網站搜尋

javascript - 無法在 node 中導入 ESM .ts 模組


我一直在嘗試在 Node.js 中導入一個用 TypeScript 編寫的 ESM 模組。但我遇到了以下錯誤:

An import path cannot end with a '.ts' extension.

Util.ts

 export class Util {
    constructor ( ) {
       
    }
      log(msg) {
        console.log(msg) 
    }
  }

index.ts

import {log} from './Util.ts'
log(task.query.criteria, payload.parameters)

我也在 package.json 中加入了 "type":"module"

我把 .ts 改成 .js 只是為了看看能否運作,然後我得到了:

Object.defineProperty(exports, "__esModule", { value: true });                         ^

ReferenceError: exports is not defined
at file:///C:/Users/abc/NestJsPOC/NestPOC/dist/main.js:2:23

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  }
}

編輯

我也嘗試過:

 var log = require('../utility/util.js');

Util.js

    function log(msg) {
      console.log(msg)
     
  }
    module.exports= { log}

index.ts

    log('hello')

錯誤:

TypeError: log is not a function

答案#1

過去幾年裡,我多次嘗試了我能找到或想到的每一種解決方案,而我剛剛找到了以下這個套件,它開箱即用,無需任何額外設定:

https://www.npmjs.com/package/tsx

它就是有效的:

npm i -D tsx
npx tsx src/index.ts

答案#2

更新於 2022 年 9 月 14 日

我已經建立了一個儲存庫,包含直接透過 ts-node 或使用 tsc 並使用 NodeJS 執行轉譯後的 esm 檔案所需的設定。https://github.com/felipeplets/esm-examples

請記住,您需要使用 ts-node 10+ 和 NodeJS 12+ 才能使用以下設置。

在我回答你的問題時(更新於 2022 年 5 月 29 日)更新的設定是:

原始答案

看起來你正在尋找如何在 Node 和 TS 中使用 ESM。

tsconfig.json(已使用 TypeScript 4.7 和 4.8 測試)

在你的 tsconfig.json 文件中,請確保具有以下設定:

{
    "compilerOptions": {
        "lib": ["ES2022"], // ES2020 in earlier versions
        "module": "ES2022", //ESNext 
        "moduleResolution": "Node",
        "target": "ES2022", // ES2020 in earlier versions
        "esModuleInterop": true,
        ...
    },
    ... 
}

package.json

請確保在您的 package.json 文件中具有以下屬性。

{ 
    ...
    "type":"module",
    ...
}

使用轉譯後的檔案運行它

你無法在 NodeJS 中直接匯入 .ts 檔案,你需要先使用 tsc 將它轉譯,之後才能在 NodeJS 的運行時匯入,因此最終你會匯入的是 .js 而不是 .ts 檔案。(如果要以 .ts 執行,請務必閱讀我答案的下一部分。使用 ts-node 執行)

在運行它時,你需要使用標誌 --experimental-specifier-resolution=node,因為這將允許你像在 TypeScript 中一樣使用沒有擴展名的導入:

node --experimental-specifier-resolution=node index

請注意,標誌的順序很重要 — 你 必須 在檔案路徑之前放置它。

你可以在 https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm 找到關於這個標誌的更多詳細信息

使用 ts-node 執行它

ts-node 是一個運行時轉譯器,因此它允許你在使用 node 時在運行時導入 TypeScript 文件。

ts-node 有一個功能允許你使用 ESM 來運行它,要使用這個功能,你需要安裝 TS Node 9.1 以上版本。關於實現方式和可能的問題,詳情請查看:https://github.com/TypeStrong/ts-node/issues/1007

要安裝它,您需要運行:

npm i -D ts-node 

要運行支援新的解析模式和 TSNode 載入器的服務,您需要運行:

ts-node 10.8+

你可以在你的 tsconfig 檔案中加入 esm 和 experimentalSpecifierResolution。

{
    ...
    "ts-node": {
        "esm": true,
        "experimentalSpecifierResolution": "node"
    }
}

現在你只需運行:

ts-node index

或者你可以設定 ts-node --esm 或 ts-node-esm,以在不設定 tsconfig.json 文件的情況下達到相同的效果。

ts-node 最高至 10.7

node --experimental-specifier-resolution=node --loader ts-node/esm index.ts

在此之後,你將能夠在專案中於執行時使用 TS 和 ESM,並且這個語句將會成為可能:

import { helloWorld } from './Util'

其中 helloWorld 是從 Util.ts 匯出的成員

重要! 我不建議在生產環境中使用 ts-node,所以這對開發環境非常方便和有用,但請確保在生產環境中將其轉譯並使用生成的代碼,以避免 TS Node 可能引起的記憶體問題。