まとめ
- tsconfig.jsonにsourcemap=trueを記載する
- module-aliasを追加する
- package.jsonに_moduleAliasesを記載する
詰まった経緯
だいぶプロジェクトがデカくなってきたのでデバッガー使いながら開発したい!
なになに、VSCodeでデバッグするには、.vscode配下にjsonファイルを2つ設置すれば良いようだ
launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "debug typescript",
"program": "${workspaceFolder}/src/app.ts",
"preLaunchTask": "typescript",
"outFiles": ["${workspaceFolder}/build/**/*.js"]
}
]
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "typescript",
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc"
],
"group": "build"
}
]
}
ふむふむ、tasks.jsonでトランスパイルしてlaunch.jsonでデバッガーを起動するようだ。
えいっ。(ピンクのデバッグボタンを押す)
Cannot launch program *** because corresponding Javascript cannot be found
「program ***」 の部分にはこちらの意図したファイルが記載されていたので、トランスパイルされたjsファイルと紐づけられないのが問題らしい。
tsconfig.jsonのsourcemapがデフォルトだとコメントアウトされている。これは怪しい。js.mapがなければトランスパイル元のtsファイルに紐づけられないのではなかろうか・・・trueにしてみる
えいっ。
(デバッガーが立ち上がり、一瞬で閉じる)
あれっ?('・ω・`)
えいっ。
(デバッガーが立ち上がり、一瞬で閉じる)
せめて何が起きたのか教えて欲しいなぁ、と思いながら左下の「Breakpoints」を眺めていると
おや?Exceptionのbreakpointがデフォルトで設定されていないようだ。チェックを入れて、もう一度デバッガーを実行してみる。
えいっ。
Cannot find module ***
何か依存関係が解消できなくて困っているようだ。
ネストの深い相対パス('../../../../../../')を避けるために、tsconfig.jsonのpathsでエイリアスを設定していたので、それが原因かもしれない。
こんな感じでbaseUrlとpathsを設定しておくと import('@/hoge')で読み込めるようになる。
ただし、TypeScriptはトランスパイルしたjsファイルのpathsを解決してくれない。トランスパイルまで成功するから「勝ったッ!第3部完!」とか思ってると、nodeで実行したタイミングで騙される。万事うまく行ってるようなツラして最後の最後で「やっぱダメでした〜」って根をあげるのはやめて欲しいな・・・
物は試し、実験的にこんなファイルを作ってみる。
index.ts
import express from 'express'
import {returnHoge} from '@/util/hoge'
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send(returnHoge())
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
util/hoge.ts
export const returnHoge = () => {
return 'hoge'
}
tsconfig.jsonでは上述の通りpathsを指定しておく。すると、ts-nodeとか使う分には問題なく動くし、トランスパイルも問題なく通る。
でもトランスパイルされたjsファイルの中身を見てみると
index.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// import 'module-alias/register';
var express_1 = __importDefault(require("express"));
var hoge_1 = require("@/util/hoge");
var app = express_1.default();
var port = 3000;
app.get('/', function (req, res) {
res.send(hoge_1.returnHoge());
});
app.listen(port, function () { return console.log("Example app listening on port " + port + "!"); });
//# sourceMappingURL=index.js.map
全くやる気のないrequireが紛れ込んでいます。さては探す気が無いな、君。
var hoge_1 = require("@/util/hoge");
なのでmodule-aliasを追加してパス解決を試みる。
yarn add --dev module-alias
そしてファイルの頭でimport
index.ts
import 'module-alias/register';
import express from 'express'
import {returnHoge} from '@/util/hoge'
const app = express();
...(以下省略)
パッケージにも指定してあげなきゃいけません
package.json
"author": "",
"license": "ISC",
"_moduleAliases": {
"@": "./build"
},
"devDependencies": {
"@types/express": "^4.17.1",
"@types/jest": "^24.0.18",
...(以下略)
今度こそ準備が整ったので、渾身のえいっ!
わーいデバッガーが立ち上がった〜
以上
普段あんまりTypeScriptでデバッガー使わないので初めて試したら、割と色んなところで詰まったのと、ほんとにmodule-aliasないとダメなの?他の方法ないの?って気になってるので、お気付きの方いたら教えてもらえたら嬉しいです。