網站搜尋

javascript - 使用 Typescript 和 ts-node 的 Node 腳本:無論配置和套件類型如何,都無法導入任何東西


我有一個 React Typescript 專案,它有多個共享結構的檔案。程式碼相似,但在某些地方差異很大,而且經常需要複製貼上檔案並更改部分資訊來建立其中一些新檔案。

我想要創建一個 Node 腳本,通過詢問使用者一些輸入來自動完成這個操作。由於我不想為此創建一個套件(因為它只是一個在我目前專案中的簡單腳本),所以我只是創建了一個名為 scripts 的資料夾,並將它放在那裡。

所以,專案結構如下:

- node_modules/
- scripts/
  - myScript/
    - helpers/
    - index.ts
    - package.json
- ...
- src/
- tsconfig.json
- package.json

為了能夠執行 Typescript,我已經安裝了 ts-node 函式庫,並且我正在透過主專案的 package.json 中的 npm script 來執行這個腳本:

"run-script": "ts-node ./scripts/myScript"

這個專案的 src 資料夾裡已經有程式碼,而這個 scripts 資料夾是附加的,並不屬於主要應用程式的程式碼,這就是為什麼我將它保存在一個外部資料夾中,因為它更像是團隊開發人員的輔助工具。

問題

每當我嘗試進行匯入時,我就會遇到這個錯誤:

throw new ERR_MODULE_NOT_FOUND(
          ^
CustomError: Cannot find module ...

如果我對套件使用動態匯入,並在我的 tsconfig 文件中設置 esModuleInterop,一切運作正常。但一旦我嘗試用相對路徑匯入一個方法,它就會出錯:

const inquirer = (await import('inquirer')).default;
const fs = (await import('fs-extra')).default;
const { getCommonPath } = await import('./helpers/getCommonPath');
Error [ERR_MODULE_NOT_FOUND]: Cannot find module ...

我以為這可能與目錄路徑有關,但如果我在匯入中使用 __dirname,它會告訴我因為路徑格式的關係不允許使用。

如果我改用非動態匯入,則會出現以下錯誤:

(node:106220) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.

但是如果我那麼做,就會出現這個錯誤:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for ...

然後我以為那應該與 ts-node 配置有關,於是我查閱了使用 ts-node-esm 的方法。但如果我這麼做,第一個錯誤又會再次出現。我也嘗試了多種 ts-node 配置(esModuleInterop: true、esm: true、module: CommonJS|ES2020|ESNext…)但都沒用。

這個問題

我需要做什麼才能寫一個 使用 Typescript 的 Node 腳本,我可以從命令列執行,並且它 允許導入外部庫和相對路徑(這些路徑也可以是 Typescript)?

謝謝你!

答案#1

實際上,我終於能夠用正常的匯入讓它運作了。我遵循的步驟如下。我遵循了 ts-node esm 的文檔:

  • 安裝 ts-node 套件。
  • 在 scripts 資料夾內建立一個 package.json,並設定 "type": "module"。
  • 將以下配置添加到你的 tsconfig.json 中:
  "ts-node": {
    "transpileOnly": true,
    "compilerOptions": {
      "module": "ESNext",
      "esModuleInterop": true
    },
    "esm": true // <--- this is the most important part
  },
  "compilerOptions": {...}
  • 在你的相對匯入中添加檔案副檔名 (.ts)。Eslint-TS 會抱怨,但這是唯一可行的方法(否則它找不到模組):
import fs from 'fs-extra';
import { getSrcPath } from './helpers/getSrcPath.ts';
  • 在你的 package.json 中使用 ts-node 執行你的節點腳本:
"run-my-script": "ts-node ./scripts/myScript"

答案#2

  1. 透過執行指令 npm install typescript ts-node @types/node 安裝必要的相依套件。

  2. 在專案的根目錄中建立一個新的tsconfig.json檔案,並使用以下內容:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "resolveJsonModule": true,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

這個配置文件告訴 TypeScript 如何將你的原始代碼編譯成 JavaScript。

  1. 在專案的根目錄中建立一個新的 src 目錄,並在此目錄中建立您的 TypeScript 檔案。例如,建立一個名為 main.ts 的檔案。

  2. 在 main.ts 中撰寫你的 TypeScript 代碼。你可以使用 import 語句來導入外部庫和相對路徑。

  3. 要從命令列執行你的腳本,你可以使用 ts-node 指令。例如,要執行 main.ts,你可以使用指令 ts-node src/main.ts。

你也可以在你的 package.json 文件中新增一個腳本,以便更容易地執行你的腳本。例如:

{
  "scripts": {
    "start": "ts-node src/main.ts"
  }
}