Gulp: Generate sourcemaps for both minified and non-minified scripts
Asked Answered
U

2

14

I'm new to gulp and have run into a problem which probably is a pretty common scenario. What I'm trying todo is compiling typescript into javascript, creating a sourcemap for it and then running uglify. I would like to have a sourcemap for the ugliyfied as well as the non uglified js.

What I'm trying to achive is the following file structure:

framework.js
framework.js.map < this won't work
framework.min.js
framework.min.js.map

This is my gulp task:

var gulp = require('gulp'),
uglify = require('gulp-uglify')
ts = require("gulp-typescript")
sourcemaps = require('gulp-sourcemaps')
rename = require('gulp-rename');

var tsProject = ts.createProject("tsconfig.json");


gulp.task('typescript', function(){
    tsProject.src()
    .pipe(sourcemaps.init())
    .pipe(tsProject()).js
    .pipe(sourcemaps.write('.')) // Write sourcemap for non-minified version
    .pipe(gulp.dest("dist"))
    .pipe(uglify()) // Code will fail here 
    .pipe(rename({suffix:'.min'}))
    .pipe(sourcemaps.write('.')) // Write sourcemap for minified version.
    .pipe(gulp.dest("dist"));
});

gulp.task('default', ['typescript']);

As you can see, I'm running sourcemaps.write() twice to get the two different files. This gives me an error

tream.js:74                                                                        
  throw er; // Unhandled stream error in pipe.                                  
  ^ GulpUglifyError: unable to minify JavaScript                                       
at createError     (C:\Users\alexa\Dropbox\code\Web\mhadmin\framework\node_modules\gulp-uglify\lib\create-error.js:6:14)

Leaving out the first one of the sourcemap.write() calls will result in a correct sourcemap for the minified version of the file.

Any ideas how to fix this?

EDIT: This is not exactly a duplicate of gulp: uglify and sourcemaps as I need to write multiple sourcemaps with multiple calls to gulp.dest()

Underdog answered 24/9, 2016 at 9:45 Comment(1)
Possible duplicate of gulp: uglify and sourcemapsMegdal
H
22

The problem is that after the first .pipe(sourcemaps.write('.')) you have two files in your stream:

framework.js
framework.js.map 

You write those two files to the file system (which is fine), but then you try to run uglify() on both of them. Since your framework.js.map file is not a JavaScript file and doesn't contain valid JavaScript code the uglify() plugin throws up.

After you have written framework.js.map to the file system there is really no reason to keep that file in the stream anymore. The vinyl file object for framework.js still has a .sourceMap property that carries all the transformations so far, meaning you can just remove the framework.js.map file from the stream.

The gulp-filter plugin let's you do just that:

var filter = require('gulp-filter');

gulp.task('typescript', function(){
  return tsProject.src()
   .pipe(sourcemaps.init())
   .pipe(tsProject()).js
   .pipe(sourcemaps.write('.'))
   .pipe(gulp.dest("dist"))
   .pipe(filter('**/*.js')) // only let JavaScript files through here
   .pipe(uglify())
   .pipe(rename({suffix:'.min'}))
   .pipe(sourcemaps.write('.'))
   .pipe(gulp.dest("dist"));
});

After .pipe(filter('**/*.js')) only the framework.js file will be in the stream and uglify() won't throw up anymore.

Hoopes answered 24/9, 2016 at 11:29 Comment(2)
Thanks a lot Sven! I just figured out exactly the same (my code is even identical to yours) solution and it works!Underdog
@Sven : isn't uglifyJS supposed to have a outSourceMap option? #41722932Referent
M
0

Seems like kind of hack, but it works

gulp.src('TypeScript/Test.ts')
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(ts(tsOptions)).js
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('./wwwroot/test'))
    .pipe(uglify())
    .pipe(rename({ extname: '.min.js' }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('./wwwroot/test'));

The magic is in plumber. Plumber prevents stopping proccess on exception. But the main interest why exception happens. So, it's pretty clear. In your code you create sourcemap via .pipe(sourcemaps.write('.')) // Write sourcemap for non-minified version and then try to uglify it. And yes, sourcemap is not js, and exception happens. With plumber this exception ignores and you achive your goal.

But I could have figured out something wrong, I recommend you to find more true-way solution.

Megdal answered 24/9, 2016 at 10:28 Comment(1)
This will work but, like you said: it's a bit of a hack. But you got me on the write track. The key is to get rid of the *.map files in the pipeline before continuing. See SvenSchoenung's answer.Underdog

© 2022 - 2024 — McMap. All rights reserved.