VSCodeでデバッグするようTypeScriptのソースマップを正しく出力するには

こちらで失敗した、TSコンパイル+Broserifyした後のJavaScriptを実行するとき、元のTSファイルに設定したブレークポイントが効くようにするためのgulpfile.js設定の続き。

どうすればTSファイル上のブレークポイントが作用するか

.jsファイル

実際にnode.exeやブラウザ、ひいてはデバッガがまず読み込むのは.jsファイルである。
そのためファイルの末尾にソースマップへのパスが書かれている。

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const startup = require("./Startup");
startup.main();
console.log("OK");

//# sourceMappingURL=Program.js.map <= ここの部分

例えば、Program.jsが./src/Program.jsにあったとしたら、ソースマップは./src/Program.js.mapにあるべきだということを意味する。

.js.mapファイル

ソースマップファイルから、JavaScriptとTypeScriptの対応関係を導くのはもちろん、TypeScriptがどこにあるかも得る。

{
    "version":3,
    "sources":[
        "Program.ts"         // *1
    ],
    "names":[],
    "mappings":"...",
    "file":"Program.js",
    "sourcesContent":[
        "..."
    ],
    "sourceRoot":"/source/" // *2
}

sourcesフィールドと、sourceRootフィールドでTypeScriptファイルを解決しているようだ。

*1 sourcesフィールド

ソースファイル名を表す。
.tsファイルがサブフォルダに入っている場合には、そのサブフォルダも含めて記述される。
(/path/to/ts-lib/Math/Vector3.tsの場合は”Math/Vector3.ts”)

*2 sourceRootフィールド

TypeScriptが置かれているだろうフォルダのルートを表す。

この例では./src/に置いているのに/source/を見に行っているので、マップから正しいJavaScript・TypeScriptの関係の対応付を行うことができなかったためと思われる。

(今更ながら).ts、.js、.js.mapをどう配置するのが良いか

トランスパイルし、その前後の生成物を使う様子はC/C++に似ている。
Visual C++で開発する場合、ファイルの配置方法は大まかに2種類、①ヘッダとソースを別フォルダに置く ②ヘッダ・ソースを同じフォルダに置く がある。

ヘッダとソースを別フォルダに置く場合

Visual C++で開発する場合の標準方式。
メリットとしては、ヘッダが一ヶ所に集まっているので配布の時目的物を収集しやすい。
デメリットとしては、ファイルを追加する場合.cppと.hを別々の、二ヶ所に置かなければならず手間がかかる。

ヘッダとソースを一緒のフォルダに置く場合

別フォルダに置いた場合のメリット・デメリットが逆になる。

TypeScriptの場合

C++と決定的に違うのは、開発者が手動で追加するファイルは1つであること。残りのファイルは自動で生成される。
そのため、C++でいうヘッダとソースを別フォルダに置く方式はデメリットが消える。
なので、.tsとトランスパイル結果の.js、.js.mapは別のフォルダに置くのがよさそう。

${workspaceRoot}/src/ts/tsconfig.json
                        somefile1.ts
                        somefile2.ts
                        ...
                     js/somefile1.js
                        somefile1.js.map
                        somefile2.js
                        somefile2.js.map
                        ...
                 index.html
                 js/bundle.js
                    bundle.js.map

となると、sourceRootには”/src/ts”ないし”../ts”を指定すればよさそうではあるが…。

VSCodeにおいて.js.mapでsourceRootに相対パスを指定する

相対パスの指定は可能、だがWindowsで”../ts”ではだめだった。”..\\ts”でなければならない。
OS依存を排除すべく、以下を参考にしgulpfile.js内で自動算出する。
https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/174

/* 関係部位のみ抜粋 */
var TSCONFIG_PATH = './src/ts/tsconfig.json';
var TS_SRC_DIR_PATH = './src/ts';
var JS_SRC_DIR_PATH = './src/js';


/// gulp transpile
// Transpile TypeScript to JavaScript
gulp.task('transpile', function() {

    var project = gulpTypeScript.createProject(TSCONFIG_PATH);

    return project
        .src()
        .pipe(gulpSourceMaps.init())
        .pipe(project())
        .js
        .pipe(gulpSourceMaps.write('.', {
            includeContent: true,
            sourceRoot: function(file) {
                return path.relative(JS_SRC_DIR_PATH, TS_SRC_DIR_PATH);
            }
        }))
        .pipe(gulp.dest(JS_SRC_DIR_PATH));
});

launch.jsonのconfigurationsにoutDirプロパティを追加

いろいろ検索してみた結果、node.jsで動作させる場合outDir必要だった。しかもこれがないと動かない。
Debugger for Chromeのようなブラウザでの実行については未確認。

ただ、VSCode 1.10.2では非推奨のためoutFilesを使え、と表示されているので、outFilesでどう書き換えるかは別途調査する必要がある。

一旦、上記設定をするとTypeScriptのソースマップについては確認ができた。
次はBrowserifyのソースマップについて確認する。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です