まえがき
別ファイルを import
する際に、いちいち相対パスで書くのが煩わしいので、絶対パスで書けるようにしたかった。
React では baseUrl
を設定することで実現していたため、Node.js でも同様に設定することにした。
試したこと
まず、tsconfig.json
の baseUrl
へ基準にしたいパスを設定。
{
"compilerOptions": {
"target": "es2020",
"strict": true,
"module": "commonjs",
"outDir": "./dist",
+ "baseUrl": "./src"
},
"include": ["src/**/*"]
}
import
を書き換える
- import UserController from '../../controller/UserController'
+ import UserController from 'controller/UserController'
この状態でts-node
を使って実行してみる。
ts-node src/server/local.ts
Error: Cannot find module 'controller/UserController'
パスをちゃんと認識してくれない...
落とし穴
Reactではreact-scripts
がtsconfig.json
の設定を解析し、Webpackのresolve.modules
に自動適用するため、特に他の設定は不要。
しかし、Node.jsではtsc
でビルドを行うため、baseUrl
だけではimport
の解決が機能しない。
これは Node.jsのrequire
(ESMならimport
)の仕様によるもので、WebpackのようにbaseUrl
を考慮しないためである。
解決方法
-
tsconfig-paths
というライブラリをインストール
ts-node
で実行する場合、tsconfig-paths
を自動適用させるために以下の設定を追加。npm install tsconfig-paths
-
tsconfig.jsonの修正
{ + "ts-node": { + "require": ["tsconfig-paths/register"] + }, "compilerOptions": { "target": "es2020", "strict": true, "module": "commonjs", "outDir": "./dist", + "baseUrl": "./src" }, "include": ["src/**/*"] }
※注意
paths
を指定するとbaseUrl
のみでは解決されなくなる。もしpaths
を設定する場合、以下のように*
で対応させると良い。{ "compilerOptions": { "baseUrl": "./src", "paths": { "*": ["*"] } } }
-
ts-node での実行方法
tsconfig.json
に以下のようなts-node.require
の設定があれば、特にオプションを指定しなくてもtsconfig-paths
が適用される。{ "ts-node": { "require": ["tsconfig-paths/register"] } }
もしこの設定がない場合は、以下のように
-r tsconfig-paths/register
を指定して実行する。ts-node -r tsconfig-paths/register src/server/local.ts
nodemon
を使う場合は、--exec ts-node
が適用されるため、特に-r tsconfig-paths/register
を指定しなくても問題なく動作する。nodemon --exec ts-node -r dotenv/config app/server/local.ts
補足
- ビルド後に node で実行する場合
tsconfig-paths
はts-node
実行時に適用されるため、ビルド後の.js
ファイルをnode
で直接実行する場合は、環境変数NODE_PATH
を設定する必要がある。ENV NODE_PATH ./dist
- 動作環境による違いを明記
-
tsconfig.json
にts-node.require
がある場合、-r tsconfig-paths/register
を明示的に指定しなくても動く - 逆に、この設定がない場合は
-r tsconfig-paths/register
を指定する必要がある
-
- エラー時の対処法
- 環境によっては
-r tsconfig-paths/register
を書かなくても動作するが、もしCannot find module '〇〇'
のようなエラーが発生する場合は-r tsconfig-paths/register
を試すと良い
- 環境によっては