gulpでTypeScript+BrowserifyしてVSCodeでブレークポイントの設定をTSファイル上でしたかったけどできなかった

gulpでtsファイルをBrowserifyして一つのjsファイルにまとめたものを、VSCodeでデバッグできるようにしようとしたが、数日かけたが結局できなかった、という話。

検証環境

${workspaceRoot}/src/tsconfig.json  # TypeScript設定ファイル
                     Startup.ts     # 実際にブレークポイントを仕掛けるファイル
                     Startup.js     # Browserifyにつかう、tscによって生成されたJavaScriptファイル
                     Startup.js.map # tscにおけるマップファイル
                     Program.ts
                     Program.js
                     Program.js.map
                /js/bundle.js       # 開発生成物となるJavaScriptファイル
                    bundle.js.map   # Browserifyにおけるマップファイル

srcフォルダ内にtsファイル、およびそれによって生成されるファイル類を格納し
jsフォルダ内に成果物となるJavaScriptファイルを置く構成を想定。

試したgulpfile.js

var gulp = require('gulp');
var gulpTypeScript = require('gulp-typescript');
var gulpSourceMaps = require('gulp-sourcemaps');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var fs = require('fs');



/* FIX VALUES FOR YOUR ENVIRONMENT */
var TSCONFIG_PATH = './src/tsconfig.json';
var INPUT_DIR_PATH = './src';
var INPUT_EXCEPTION_PATTERNS = [];
var OUTPUT_FILE_PATH = './js/bundle.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('.'))
        .pipe(gulp.dest(INPUT_DIR_PATH));
});


/// gulp build
gulp.task('build', [ 'transpile' ], function() {

    fs.readdir(INPUT_DIR_PATH, function(err, files) {
        if(err) {
            throw err;
        }

        var filesToBeBundled = [];
        var regexJS = new RegExp('.+\.js$');
        var regexes = [];
        INPUT_EXCEPTION_PATTERNS.forEach(function(pattern) {
            regexes.push(new RegExp(pattern));
        });

        files.forEach(function(file) {
            var matched = false;
            if(regexJS.test(file)) {
                regexes.forEach(function() {
                    matched &= r.test(file);
                });
                if(!matched) {
                    filesToBeBundled.push(path.join(INPUT_DIR_PATH, file));
                }
            }
        });

        var option = {
            entries: filesToBeBundled,
            debug: true
        };
        return browserify(option)
            .bundle()
            .pipe(source(OUTPUT_FILE_PATH))
            .pipe(buffer())
            .pipe(gulpSourceMaps.init({ loadMaps: true }))
            .pipe(gulpSourceMaps.write('.'))
            .pipe(gulp.dest('.'));
    });
});

正しくBrowserifyによって生成物js/bundle.jsおよびそのソースマップはできるものの、tsファイル上に設定したブレークポイントは「生成されたコードがみつからないので….」と無効になってしまう。
ソースマップが正しく構成されていないようだ。

Startup.js.map

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

Program.js.mapも同様にsourceRootがおかしな場所を指しているのでこれを直す必要がありそう。

bundle.js.map

{
    "version":3,
    "sources":[
        "js/node_modules/browser-pack/_prelude.js",
        "js/src/Program.js",
        "js/src/Startup.js"
    ],
    "names":[],
    "mappings":"...",
    "file":"js/bundle.js",
    "sourceRoot":"/source/",
    "sourcesContent":[
        "..."
    ]
}

bundle.js

bundle.js内に記述されているソースファイルのパスもこれでよいのだろうか。。。
js/bundle.js.map、が正しそうな。

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const startup = require("./Startup");
startup.main();
console.log("OK");



},{"./Startup":2}],2:[function(require,module,exports){
"use strict";
class Startup {
    static main() {
        console.log('Hello World');
        return 0;
    }
}
module.exports = Startup;



},{}]},{},[1,2])


//# sourceMappingURL=bundle.js.map

まずはsourceRootの意味と、それを正しく設定するようgulpfile.jsを書き直そう。

コメントを残す

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