起こったこと
Node.js(Express)環境でtypescriptを使ったAPIの開発環境でホットリロードを実装しようとしたところ、めちゃくちゃ詰まった。
最初に試したことはts-nodeとnodemonの組み合わせ。ts-nodeがtsファイルを読み込めず、ずっとエラーを吐いていた。。。
以下、解決した方法と環境
実行環境
- Node.js 20.0.0
- express 4.19.2
- typescript 5.3.3
- nodemon 3.1.0
- tsx 4.7.2
解決方法
結論、ts-nodeではなく、tsxをnodemonと一緒に利用することで解決した。
package.jsonのstartコマンドを記載するだけ。tsconfig.jsonなど他のファイルの変更は不要。
yarn add -D tsx
"scripts": {
"test": "echo \"Error: no tes@t specified\" && exit 1",
"start": "nodemon --exec tsx './app.ts'",
"up": "yarn install && yarn start"
},
この状態でdocker-compose up時にstartコマンドも実行するようにすればコンテナの起動と同時にホットリロードが走るようになった。
※tsx './app.ts'
の部分はファイルのパスをシングルクォーテーションで囲む必要があります。
原因
ts-nodeとNode.js20系とESMの組み合わせの相性が悪いっぽかった。(ts-nodeの実行時にesmオプションを付けたり、package.jsonにtype: module
を記載してみたりしたが以下のエラーが直らなかった。)
原因は不明。。。
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/watanabejin/workspace/business_card/batch/index.ts
at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
at defaultLoad (node:internal/modules/esm/load:143:22)
at async nextLoad (node:internal/modules/esm/hooks:750:22)
at async nextLoad (node:internal/modules/esm/hooks:750:22)
at async Hooks.load (node:internal/modules/esm/hooks:383:20)
at async handleMessage (node:internal/modules/esm/worker:199:18) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
他の学び
はじめ、windows × WSLの構成でdockerコンテナを起動し、プロジェクト自体はWSL上ではなくWindowsのローカルに置いていたため、コンテナのパフォーマンスが著しく低かった。
これはWindows上のファイルシステムがWSL Ubuntu自身のファイルシステムとは違うことによって起こるらしい。
下記の記事がとても勉強になりました。
参考
最終的にHyperVを利用してコンテナ起動するように修正したらパフォーマンスの問題は改善されました。
20240418 追記
メンバーの環境によってはdocker起動時に「System」タスクがCPUを食い尽す事象が発生した。(タスクマネージャから確認)
最終的には下記のような形で落ち着いた。
"scripts": {
"start": "nodemon ./dist/index.js",
"build": "npx tsc",
"build:watch": "npx tsc -w",
"dev": "yarn install & yarn run build:watch & yarn start",
"up": "yarn install && yarn start"
},
jsファイルを直接実行した方が安全かもしれないという結論に。