2018年9月15日土曜日

VSCode で TypeScript のデバック設定

VSCode (Visual Stadio Code) で TypeScript デバックするための設定は、ネット上で情報がたくさんあるのですが、なぜか少しずつ違っています。そして、動作しなかったりします。

今回は、単純なコードをデバックできるだけの設定をメモ書きします。

事前準備
Visual Stadio CodeTypeScriptNode.js がインストールされていることを確認します。

VSCode バージョン確認

$ code -v
1.27.1
5944e81f3c46a3938a82c701f96d7a59b074cfdc
x64

TypeScript バージョン確認

$ tsc -v
Version 3.0.3

Node.js バージョン確認

$ node -v
v10.10.0

確認できない場合、インストール作業を行ってください。インストール方法はネット上でいろいろ説明がありますが、次のページなどを参考にしてください。
TypeScriptチュートリアル① -環境構築編-

もしインストール中にVSCodeを開いていたら、一旦終了し開き直したほうが良いでしょう。


今回のサンプル用として、次のコードを使用します。

class Startup {
    public static main(): number {
        console.log('Hello World');
        return 0;
    }
}
Startup.main();
ファイル名 sample.ts とします。
コンパイル設定
TypeScriptのコードをデバックするためにはコードをコンパイルし、JavaScriptファイル(xxx.js)とソースマップファイル(xxx.map)を生成する必要があります。もちろん手動でコンパイルしても大丈夫ですが、せっかくなので、VSCodeに自動でコンパイルさせるための設定をします。
  1. コンパイルオプション指定

    コンパイルオプションの設定ファイル(tsconfig.json)を作成します。tsconfig.json は TypeScript のファイルで、プロジェクトのルートディレクトリに置きます。

    新規にファイルを作成し、次のように記述します。最後に、tsconfig.json という名前で保存します。

    {
        "compilerOptions": {
            "target": "es5",
            "module": "commonjs",
            "sourceMap": true
        }
    }
    
    "sourceMap": true によってコンパイル時、ソースマップファイルが生成されます。

    この設定でコンパイルが実行可能かと思います。

    VSCode メニューの 「ターミナル」→「ビルドタスクの実行」→「tsc:ビルド」 を選択すると、 js及びmapファイルが生成されるのが確認できます (「tsc:ウォッチ」 を選択するとタスクが常駐し、tsソースが保存される度にコンパイルが実行されます )。


  2. VSCode タスク設定

    VSCodeから条件に応じて、処理を実行する機能が「タスク」です。今回はデバック時に事前に、TypeScriptコードをコンパイルするためのタスクを設定します。
    タスク設定には幾つも方法があるようですが、例えば次のようにします。

    メニューの「ターミナル」→「タスクの構成」→「テンプレートからtasks.jsonを生成」を選択し、「tsc:ビルド」 を選んで tasks.json を生成させます。

    「コマンドパレット」 に、 >tasks configure task と入力してもタスク構成にアクセス可能です。
    要は、.vscode/tasks.json を生成することが必要な訳です。

    生成したtasks.jsonファイルの内容は以下の通りですが、特にコードの変更は必要ありませんが、label で名前(8行目)だけ付けておきます。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
            {
                "type": "typescript",
                "label": "tsc",
                "tsconfig": "tsconfig.json",
                "problemMatcher": [
                    "$tsc"
                ]
            }
        ]
    }
    
    syntax2html

以上で、デバック構成設定前の準備が完了です。


余談ですが、TypeScriptのコードはコンパイルしなくても実行可能です。その場合、右クリックメニューの 「Run Code」 で実行できますが、事前に ts-node モジュールをインストールしておく必要があります。
ターミナルから次のようにインストールします。

$ npm install -g ts-node
デバッグ設定
デバックでは構成ファイル(launch.json)を準備する必要があります。

VSCodeのメニューの 「デバック」→「構成を開く」 を選択し、「Node.js」を選ぶと launch.js が生成されます。

「コマンドパレット」 に、 >debug open launch.json と入力しても同様な事が可能です。

生成された launch.json のコードです。

{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "program": "${workspaceFolder}/sample.ts",
            "outFiles": [
                "${workspaceFolder}/**/*.js"
            ]
        }
    ]
}

これを次のように変更します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: ....
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "preLaunchTask": "tsc",
            "program": "${workspaceFolder}/${fileBasenameNoExtension}.ts",
            "smartStep": true,
            "outFiles": [
                "${workspaceFolder}/**/*.js"
            ]
        }
    ]
}
syntax2html

変更は三点です。

preLaunchTask (11行目)
デバッグセッションの開始前に起動するタスクを指定します。
ここでは先程コンパイル設定で作成したタスクのラベル名("tsc")を指定します。
program (12行目)
デバッガを起動するときに起動する実行可能ファイルを指定します。
自動生成されコードでは特定のファイル名を指定していましたが、${fileBasenameNoExtension} という記述に変更しました。${fileBasenameNoExtension} は現在開いているファイル名から拡張子を除いた文字列を返します。つまり、作業ディレクトリ上なら任意のソースファイルをデバックできることになります。
smartStep (13行目)
true の場合、マップファイル対象外のコードのステップを省略します。デバック中変な js コードが表示されたりしますが、それを省きます。ただ完全ではないようです。状況に応じて、"skipFiles" パラメータでスキップするソースを指定することが必要かもしれません。

preLaunchTask の設定ではなく、コンパイル設定でも紹介した、VSCode メニューの 「ターミナル」→「ビルドタスクの実行」→「tsc:ウォッチ」 でも同じように変更時にコンパイルされます(VSCode起動時にウォッチを実行する必要はありますが・・・)。

デバック実行とその他
以上でVSCodeの設定が完了したので、デバックを実行してみます。
一応、動作するのが確認できました。

この他に、TypeScriptファイルとJavaScriptファイルが同じディレクトリにありますが、それぞれ別のディレクトリに配置する設定を考えてみます。

TypeScriptファイルは src に、JavaScript と map ファイルは build に配置します。
まず tsconfig.json ですが、次のように、outDir パラメータでコンパイル時の出力先を指定します(6行目)。
1
2
3
4
5
6
7
8
{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "sourceMap": true,
        "outDir": "build"
    }
}
syntax2html

次に launch.json ですが、program パラメータに TypeScriptファイルのディレクトリを(13行目)、outFilesにJavaScriptのディレクトリを指定します(16行目)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: ....
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "preLaunchTask": "tsc",
            "program": 
                "${workspaceFolder}/src/${fileBasenameNoExtension}.ts",
            "smartStep": true,
            "outFiles": [
                "${workspaceFolder}/build/**/*.js"
            ]
        }
    ]
}
syntax2html
以上で、ディレクトリを分けてもデバックが動作すると思います。

参考:
VSCode + Typescript でデバッグを有効にする
VisualStudioCode + TypeScript でブレークポイントが効かなかった問題(解決)
Visual Studio Code (VS Code) の非公式日本語訳
Visual Studio Code Docs
第2回 Visual Studio Codeのデバッグ構成ファイルの基本:Node.js編