vite-nodeで実行するTypeScriptのコードのスタックトレースの行を正しく表示したい
ので調べたんだけど、簡単に解決できる方法はなさそう
→なんかできました 続:vite-nodeで実行するTypeScriptのコードのスタックトレースの行を正しく表示したい
背景
最終的にJavaScriptランタイムで実行されるJSコードは、元のソースコードと行がずれることが多い
TypeScriptによるコンパイルやminifyなど
デバッグの際にこれは不便なため、SourceMapという仕組みがある
SourceMapには元のソースコードと変換後のソースコード位置の対応関係が記述されているので、ランタイムがそれを解釈していい感じにデバッガに表示してくれる
が、vite-nodeで.tsなコードを実行するときに、SourceMapを読ませる方法が分からない
試したこと・調べたこと
vite-nodeにSourceMapを出力させる
これは簡単で、$ vite-node --options.sourcemap="inline" src/index.tsとすれば、コンパイルされた.jsコードにDataUrlの形式でSourceMapが挿入される
inline以外だと生成されないっぽい
trueだと生成されない謎
https://vitejs.dev/config/build-options.html#build-sourcemap
実際に埋め込まれているかどうかは、vite-nodeのコマンドラインオプションでVITE_NODE_DEBUG_DUMP=loadと指定すると.jsコードがダンプされるので確認できる
https://github.com/vitest-dev/vitest/tree/main/packages/vite-node#debug-transformation
tsconfig.jsonのcompilerOptions.sourceMapは参照されないっぽい
vite-nodeコマンドがどのような経路でコードを実行するのか
$ vite-node <file>を叩くと、vite-nodeのあるvite-node.mjsが実行される
vite-nodeパッケージのpackage.jsonに以下のように書かれているので
code: json
"bin": {
"vite-node": "./vite-node.mjs"
},
https://github.com/vitest-dev/vitest/blob/main/packages/vite-node/package.json
vite-node.mjsのshebangには#!/usr/bin/env nodeと書いてあるので、ここからnodeで実行される
その後の処理を辿っていくと、Node.jsのVM APIを使って、コマンド引数で指定したコードを実行していることが分かる
https://github.com/vitest-dev/vitest/blob/baf5e755af864a310468dbb556f0aa65ffd3cae0/packages/vite-node/src/client.ts#L280
TypeScript+Node.jsでsourcemap対応を加えてエラーログ調査を行いやすくしたいに書いてある方法を試した
--enable-source-mapsを指定する
https://nodejs.org/dist/latest-v16.x/docs/api/cli.html#--enable-source-maps
試行錯誤
$ node --enable-source-maps node_modules/vite-node/vite-node.mjs ./src/index.tsみたいに大元のnodeに指定したけどだめだった
$ export NODE_OPTIONS=--enable-source-mapsして環境変数で指定してもだめ
調べたところ、vmではsourceMapが(現時点では)サポートされていないらしい
https://github.com/nodejs/node/issues/8042
あんまり関係ないかもしれないけど、evalの方はつい最近sourceMapがサポートされた?みたいなので、そのうちvmでもサポートされるかも
https://github.com/nodejs/node/issues/43047
node-source-map-supportを使う
ユーザコード側に書いても、vite-nodeの実行側に書いてもだめ
調べたが、source-map-supportはそもそもインラインSourceMapをサポートしていないっぽい
https://github.com/evanw/node-source-map-support/issues/33
メンテもあんまりされていないみたい......
まとめ
詰みです
vmでSourceMapがサポートされていない以上、source-map-supportを使うしかなさそうなんだけど、source-map-supportはインラインSourceMapをサポートしていないので他の形式のSourcemapを作る必要があるが、viteはインライン以外の形式をサポートしていない
やはりts-nodeやvite-nodeでのお手軽.ts実行を諦めて、rollupやparcelとかでちゃんとビルドするしか無いのか......
って思ったんだけど、vitestはvite-nodeを使っているわけで、vitestだと正しいコード位置がテスト結果に表示されているので、なんとかなる可能性がある
vitestのコード見てみたけど、エラーメッセージをパース→ViteNodeServerが持っているTransform結果からSourceMapデータを取得→置き換えて標準出力という感じだった
このへん
https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/utils/source-map.ts
なので、スタックトレース取得に割り込んでSourceMapを元に置換して上げれば良さそう
スタックトレースへのフックはsource-map-supportみたいに、V8エンジンのStack Trace APIのError.prepareStackTraceを使えばできそう
が、これをやるにはvite-nodeのvm呼び出し周りに手を加えるか、ユーザコード内からViteNodeServerにアクセスする必要がありそうで結構大変
そこまでやるよりも、おとなしくvite-nodeを使うのを止めるのが正解っぽい
#2022Aug