问题
I'm working on a Typescript project that is transpiled to ES5 JS and then run through browserify to create a single .js bundle and sourcemap. The bundled sourcemaps point to the transpiled JS rather than the source TS even though I am generating sourcemaps which properly point to the source TS when transpiling to JS.
It's as if browserify is ignoring the existing sourcemaps pointing to the TS code and creating its own new maps to the transpiled JS code.
Here are my gulp tasks for reference- code is compiled to a temp folder and then browserified from there. This uses browserify-incremental to support incremental compilation.
Thanks!
Note: Via other SO questions I have already tried using tsify, per my understanding it won't work with my project as we use import syntax & commonjs, it reports compile issues where tsc and gulp-typescript do not (same errors whether used via gulp or via CLI). I also tried minifyify but it did not solve the issue.
var gulp = require('gulp'),
ts = require('gulp-typescript'),
browserify = require('browserify'),
browserifyInc = require('browserify-incremental'),
source = require('vinyl-source-stream'),
del = require('del'),
sourcemaps = require('gulp-sourcemaps'),
buffer = require('vinyl-buffer'),
xtend = require('xtend');
var tsProject = ts.createProject('tsconfig.json');
//COMPILE TS
gulp.task('compileTs', function () {
var sourceTsFiles = [config.src.tsFiles, config.src.tsTypes];
var tsResult = gulp.src(sourceTsFiles)
.pipe(sourcemaps.init())
.pipe(ts(tsProject));
return tsResult.js
.pipe(sourcemaps.write('.', {
//includeContent: false,
//sourceRoot: "../../src/js/"
}))
.pipe(gulp.dest(config.tempDir));
});
//BUNDLE BUILT TS->JS
gulp.task('bundleJs', [], function () {
var b = browserify(xtend(browserifyInc.args, {
entries: config.tempDir + '/main.js',
extensions: ['.js', '.jsx'],
debug: true
}));
browserifyInc(b, {cacheFile: config.tempDir + '/browserify-cache.json'});
return b.bundle()
.pipe(source('main.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(config.dest.jsDir));
});
回答1:
Short answer
In the compileTs
task you need to write the sourcemaps to the output .js
files, instead of dedicated .map
files. You also need to set includeContent
to true, and specify the correct sourceRoot
.
Then in the bundleJs
task, having browserify debug
true is enough to generate sourcemaps.
More details
Some package doesn't provide the necessary source data to the sourcemaps utility in the bundle task. Luckily sourcemaps can re-read the .ts
file. For that recovery step to work, it needs correct file paths, so that's why the correct sourceRoot
in the TypeScript compilation task is so crucial.
There seem to be other gotchas here as well. For example if you write the sourcemaps to a dedicated .map
file in the TypeScript compilation task, then later the bundle task will generate sourcemaps that point to the compiled .js
files. So it's again crucial that the compilation task embeds the sourcemaps into the actual .js
files.
If the debug
flag for browserify is true, it will generate sourcemaps. The extra gulp-sourcemaps
layering here has a buggy interaction and should be removed.
A working example from real life
Directory structure
proj
/ts
/def
my-declarations.d.ts
/src
my-sources.ts
/tmp
temp-files-get-created-here-by-gulp.js
tsconfig.json
/web
/static
/js
final-result-goes-here.js
gulpfile.js
package.json
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": true,
"removeComments": true,
"declaration": false,
"jsx": "React",
"target": "ES5",
"module": "CommonJS"
},
"exclude": [
"tmp"
]
}
package.json
{
"name": "my-awesome-project",
"version": "0.1.0",
"devDependencies": {
"browserify": "^13.0.1",
"gulp": "^3.9.1",
"gulp-sourcemaps": "^1.6.0",
"gulp-typescript": "^2.13.6",
"gulp-uglify": "^1.5.3",
"gulp-util": "^3.0.7",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
}
}
gulpfile.js
var path = require('path');
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var gutil = require('gulp-util');
var ts = require('gulp-typescript');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
var debug = false;
var paths = {
tsConfig: 'ts/tsconfig.json',
scriptsSrc: ['ts/def/**/*.ts', 'ts/src/**/*.ts', 'ts/src/**/*.tsx'],
scriptsDst: 'web/static/js',
outDev: 'bundle.dev.js',
outFinal: 'bundle.js',
tempDst: 'ts/tmp',
entry: 'ts/tmp/entry.js'
};
var tsProject = ts.createProject(paths.tsConfig, { noExternalResolve: true });
gulp.task('ts', function () {
var tsResult = tsProject.src().pipe(sourcemaps.init()).pipe(ts(tsProject));
return tsResult.js.pipe(sourcemaps.write('', { debug: debug, includeContent: true, sourceRoot: './ts/src' })).pipe(gulp.dest(paths.tempDst));
});
gulp.task('dev', ['ts'], function() {
var bsfy = browserify({ entries: paths.entry, debug: true }); // Debug true generates sourcemaps
return bsfy.bundle()
.on('error', gutil.log)
.pipe(source(path.join(paths.scriptsDst, paths.outDev)))
.pipe(buffer())
.pipe(gulp.dest('./'));
});
gulp.task('final', ['ts'], function() {
process.env.NODE_ENV = 'production';
var bsfy = browserify({ entries: paths.entry, debug: false });
return bsfy.bundle()
.on('error', gutil.log)
.pipe(source(path.join(paths.scriptsDst, paths.outFinal)))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest('./'));
});
// Rerun the dev task when a file changes
gulp.task('watch', function() {
gulp.watch(paths.scriptsSrc, ['dev']);
});
// By default run all the tasks
gulp.task('default', ['dev', 'final']);
回答2:
If you use both tasks at the same time, the second task will write new source maps. I'd suggest, that you only write source maps once, in the compileTs
task.
I think this is the only problem in your tasks.
来源:https://stackoverflow.com/questions/33903456/gulp-typescript-browserify-bundled-sourcemap-points-to-transpiled-js-rather-t