TypeScript な Express を ts-node で動かしてて tsconfig.json
に path alias を設定したんだけどエラーになってなんもわからん。ってなったのでメモ
環境
- typescript:
^4.5.4
- ts-node:
^10.4.0
- ts-node-dev:
^1.1.8
結論
tsconfig-paths を使って ts-node 実行時に -r tsconfig-paths/register
オプションを渡してあげれば OK
package.json
(entry point が src/index.ts
の場合)
{ "scripts": { "start": "ts-node -r tsconfig-paths/register src/index.ts", "dev": "ts-node-dev -r tsconfig-paths/register src/index.ts", "build": "tsc" } }
tsconfig.json
{ "compilerOptions": { // … "baseUrl": "./", "paths": { "@/*": ["src/*"] } }
/src
内のファイルを @/
で import できるようにパスエイリアスを設定した
npm script
package.json
{ "scripts": { "start": "ts-node src/index.ts", // … } }
ts-node で path alias が効かなくてエラーになる
$ npm run start > server@1.0.0 start > ts-node src/index.ts [ERROR] 23:53:57 Error: Cannot find module '@/data/xxx'
パスエイリアスを使っている module のところでエラーになる
なんもわからん…
ts-node は単体では path alias に対応してないっぽい
That's the node.js error - TypeScript is working fine, but node will never be able to resolve an alias like that unless TypeScript emits code that rewrites paths.
cf. tsconfig.json/paths not working with ts-node · Issue #138 · TypeStrong/ts-node · GitHub
tsconfig-paths を使う
ts-node -r tsconfig-paths/register
として呼び出せば ts-node でも path alias が効くようになるっぽい!
$ npm i -D tsconfig-paths
package.json
を書き換える
{ "scripts": { - "start": "ts-node src/index.ts", + "start": "ts-node -r tsconfig-paths/register src/index.ts", // … }
再実行
$ npm run start > server@1.0.0 start > ts-node src/index.ts Start on port 4000.
₍ ᐢ. ̫ .ᐢ ₎👌 解☆決
tsconfig.json に設定する方法もある
typescript-transform-paths を使えば設定を tsconfig.json
にまとめられて npm script で -r tsconfig-paths/register
オプションを渡さなくてもOKになる
cf. tsconfig.json/paths not working with ts-node · Issue #138 · TypeStrong/ts-node · GitHub
$ npm i -D typescript-transform-paths
package.json
{ "scripts": { - "start": "ts-node -r tsconfig-paths/register src/index.ts", + "start": "ts-node src/index.ts", // … }
tsconfig.json
{ + "ts-node": { + "transpileOnly": true, + "require": [ + "typescript-transform-paths/register", + "tsconfig-paths/register" + ] + }, "compilerOptions": { // …
👇
$ npm run start > server@1.0.0 start > ts-node src/index.ts Start on port 4000.
₍ ᐢ. ̫ .ᐢ ₎👌
ts-node-dev での path alias
ts-node では開発時にファイルを監視してのホットリロードができません。以前は nodemon を使ってたのですが ts-node-dev の方が高速でナウでヤングらしいので導入してみました。
$ npm i -D ts-node-dev
ts-node-dev もデフォルトではパスエイリアスが効かない
ts-node-dev も ts-node と同様でデフォルトでは tsconfig.json
に書かれているパスエイリアスが効かないので実行時に -r tsconfig-paths/register
オプションを渡してあげる必要があります
package.json
{ "scripts": { "start": "ts-node -r tsconfig-paths/register src/index.ts", "dev": "ts-node-dev -r tsconfig-paths/register src/index.ts" // … } }
👇
$ npm run dev > server@1.0.0 dev > ts-node-dev -r tsconfig-paths/register src/index.ts [INFO] 00:55:03 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.5.4) Start on port 4000.
src/index.ts
や import しているファイルを変更した際に自動的に再起動されればOK
₍ ᐢ. ̫ .ᐢ ₎👌👌👌
⚠ ts-node-dev では typescript-transform-paths を使って tsconfig.json
にまとめる方法がうまく動作しない
ts-node と同じように tsconfig.json
にパスエイリアスの設定をまとめられるかと思ったけど、うまく動作させられなかった
tsconfig.json
に ts-node-dev
のセクションを追加
{ "ts-node": { // … }, + "ts-node-dev": { + "transpileOnly": true, + "require": [ + "typescript-transform-paths/register", + "tsconfig-paths/register" + ] + }, "compilerOptions": { // …
package.json
の npm script からオプションを削除
{ "scripts": { "start": "ts-node src/index.ts", - "dev": "ts-node-dev -r tsconfig-paths/register src/index.ts" + "dev": "ts-node-dev src/index.ts" // … }
👇 パスエイリアスが解決できない
$ npm run dev > server@1.0.0 dev > ts-node-dev src/index.ts [INFO] 01:01:28 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.5.4) Error: Cannot find module '@/data/xxxx' … [ERROR] 01:01:32 Error: Cannot find module '@/data/xxxx'
typescript-transform-paths
は ts-node-dev
のセクションを作れないっぽいです。
もしかしたら tsconfig.json
の compilerOptions
内で設定すればうまく動作させられるかもですが、そこまでは調べませんでした。
所感
typescript-transform-paths
を使うとパスエイリアスの解決関連を tsconfig.json
にまとめられて npm script の見た目はシンプルになるけど、開発で使うだろう ts-node-dev でいい感じに動作させられなかったし、パッケージも増えてしまうのでシンプルに ts-node, ts-node-dev 両方に -r tsconfig-paths/register
オプションを渡してしまうのが良さそうだと思いました。
package.json
{ "scripts": { "start": "ts-node -r tsconfig-paths/register src/index.ts", "dev": "ts-node-dev -r tsconfig-paths/register src/index.ts" // … } }
おわり。
[参考]