Search code examples
typescriptgulpbrowserifysource-maps

Sourcemaps horribly broken using typescript and browserify/gulp


I am successfully getting sourcemaps output from my build process which uses browserify with gulp. However, the sourcemaps don't work when debugging - breakpoints often jump to a different line when I set them (in Chrome), and it is clear the script is not actually pausing where it says it is. When I hover over variables to view their values, it shows the wrong thing, and so on. I used this tutorial as a basis, so it seems like it should work.

The relevant build step in my gulpfile.js is:

return browserify({
  basedir: '.',
  debug: mode === 'dev',
  entries: [`${paths.src}/app/${buildConfig.appFolder}/${buildConfig.appSrc}`],
  cache: {},
  packageCache: {},
})
  .plugin(tsify)
  .bundle()
  .pipe(source('app.js'))
  .pipe(gulp.dest(`${paths.dist}/app/${buildConfig.appFolder}`))
  .on('error', err => {
    console.error(err.toString());
    done(err);
  });

And tsconfig.json is:

{
  "compilerOptions": {
    "lib": ["es2018", "dom"],
    "target": "es2015",
    "jsx": "react",
    "moduleResolution": "node",
    "diagnostics": true,
    "types": [
      "react",
      "react-dom",
      "lodash"
    ]
  }
}

Solution

  • Try setting the compiler options:

    {
      "compilerOptions": {
         "sourceMap": true,
         "inlineSources": true
      }
    }
    

    "sourceMap": true tells typescript to emit source maps. "inlineSources": true tells it to embed the typescript source within the source map itself.

    If this still doesn't work, you could try using "inlineSourceMap": true (in conjunction with inlineSources) which causes the sourcemaps to actually be inlined within the emitted javascript (best to make sure production builds disable this to avoid bloating your final bundles)

    Whether this will work with your exact gulp / browserify setup I'm unsure. That tutorial you linked mentions adding:

    var sourcemaps = require('gulp-sourcemaps');
    
    ....
        .pipe(sourcemaps.init({loadMaps: true}))
        .pipe(sourcemaps.write('./'))
    

    Which may be worth a try as well, though this appeared to be in relation to uglify, https://www.typescriptlang.org/docs/handbook/gulp.html#uglify

    ref: https://www.typescriptlang.org/docs/handbook/compiler-options.html

    Overall I've found sourcemaps with typescript to be frustrating - even with a correct setup I still find occasionally I get poor breakpoint / code stepping behavior, though it has definitely been improving over the years.

    As a general tip I find having third party dependencies split off to a separate bundle, and then blackboxing this in the chrome dev tools to help, as it avoids stepping into library code for promises, observables, etc