Debugging variables not working with gulp sourcemaps + uglify - javascript

I have the following gulp task for bundling javascript:
gulp.task('js', function () {
return gulp.src(paths.js)
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(concat('bundle.min.js'))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'));
});
When I run this in the Chrome dev tools, sourcemaps are found and breakpoints work, but variables can't be debugged.
Take this example chunk of angular code:
iarApp.config(['$animateProvider', function ($animateProvider) {
$animateProvider.classNameFilter(/angular-animate/);
}]);
If I add a breakpoint to see the value of $animateProvider, I get the following:
But if I turn off variable mangling in Uglify:
.pipe(uglify({ mangle: false }))
Then it works:
So it seems that the gulp-sourcemaps plugin can't follow up variables after Uglify mangles the names.
Can anyone else get the same issue and/or know a solution?

Turns out this is just not possible currently, since this is not part of the specification for source maps.
There are some proposals to add this feature, so we will have to wait until the spec and implementations are updated.

Related

Very slow BrowserSync server startup with Gulp

I'm using BrowserSync in server mode (using its built-in static server) with GulpJS on a local project, and everything seems to be working correctly except that the BrowserSync server is very slow to startup. BrowserSync itself seems to initialize right away when I run Gulp, but it takes about 4 to 5 minutes (and occasionally more) for the server to start and for it to return the access URLs. During this period, everything continues to run and BrowserSync responds to reload() calls and such, but access is not available via the usual URLs (in this case, localhost:3000 and localhost:3001). Once the access URLs are returned, the server has seemingly started and BrowserSync's page refreshes work fine and are actually very speedy.
I have tried several different configurations of my gulpfile.js, trying different ways to initialize BrowserSync, different approaches to calling the stream() and reload() methods (including trying BrowserSync's basic Gulp/SASS "recipe"), and different port numbers, but all configurations had the same problem. I even tried disabling my firewall and AV software (Avast), but nothing.
I'm running Windows 8.1, if that's relevant. BrowserSync is freshly installed locally to the project via NPM, and fresh local installs to other directories have the same problem. NPM, Ruby, Gulp, and all modules seem to be up-to-date. For what it's worth, all of my other experience with Ruby, Gulp, and Node.js have been very smooth and problem-free.
I can't find any other posts mentioning this problem and am beginning to think this is normal behavior. Is this normal, and, if not, does anyone have any ideas of things to try? This delay is not the end of the world since the BrowserSync server does always start (eventually), but it's still a kink in my workflow that I'd rather fix than just deal with.
Finally, here is my gulpfile.js:
/* File: gulpfile.js */
var gulp = require('gulp'),
gutil = require('gulp-util');
jshint = require('gulp-jshint');
sass = require('gulp-sass');
concat = require('gulp-concat');
uglify = require('gulp-uglify');
sourcemaps = require('gulp-sourcemaps');
imagemin = require('gulp-imagemin');
browserSync = require('browser-sync').create();
gulp.task('default', ['watch'], browserSync.reload);
// JSHint
gulp.task('jshint', function() {
return gulp.src('src/js/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));
});
// Build JS
gulp.task('build-js', function() {
return gulp.src('src/js/**/*.js')
.pipe(sourcemaps.init())
.pipe(concat('main.js'))
//only uglify if gulp is ran with '--type production'
.pipe(gutil.env.type === 'production' ? uglify() : gutil.noop())
.pipe(sourcemaps.write())
.pipe(gulp.dest('public/www/js/core'));
});
// Build CSS
gulp.task('build-css', function() {
return gulp.src('src/sass/**/*.{sass,scss}')
.pipe(sourcemaps.init())
.pipe(sass()).on('error', handleError)
.pipe(sourcemaps.write()) // Add the map to modified source.
.pipe(gulp.dest('public/www/css/core'))
.pipe(browserSync.stream({match: '**/*.css'}));
});
// ImageMin
gulp.task('imagemin', function () {
return gulp.src('src/img/*')
.pipe(imagemin({
progressive: true,
svgoPlugins: [{removeViewBox: false}]
}))
.pipe(gulp.dest('public/www/img'));
});
// Handle errors
function handleError(err) {
console.log(err.toString());
this.emit('end');
}
// Watch function
gulp.task('watch', function() {
browserSync.init({
server: "./public/www",
//port: 3002
});
gulp.watch('src/js/**/*.js', ['jshint']);
gulp.watch('src/sass/**/*.{sass,scss}', ['build-css']);
gulp.watch('src/js/**/*.js', ['build-js']);
gulp.watch('src/img/*', ['imagemin']);
gulp.watch("public/www/css/**/*.css").on('change', browserSync.reload);
})
The BrowserSync Twitter account suggested that I set the "online" option to true, and...it seems to have worked!
I set it in BrowserSync's init like so:
browserSync.init({
server: "./public/www",
online: true
});
...and the delay is gone!
Going by the BrowserSync docs ( http://www.browsersync.io/docs/options/#option-online ), it seems that setting the online option to true skips the online check. So, I guess that check was somehow what was causing the delay? That seems odd to me, but it's working better now.
In my case I had this code in gulpfile which delay startup about 50 seconds
gulp.watch('./**/*.{js,html}').on('change', browserSync.reload);
and the problem was in the glob string. It inspects even node_modules folder. And I did some changes
gulp.watch(['./scripts/**/*.{js,html}', './index.html'])
.on('change', browserSync.reload);
I think that it is performance feature, that we should more exactly specify glob.

Issue with asynchronous build task in gulp

EDIT: it appears the pretty:true from Jade is from where the problem comes from. any idea why ?
I've got a bit of trouble here. Let me explain what I'm trying to do :
Here is what is supposed to happens:
file.jade > intermediate.html > index.html
The jade file outputs a html, then the html outpus a minified html. All in the watch function of course.
What I wrote to achieve this effect:
/* ===== TEMPLATES ===== */
gulp.task('templates', function() {
gulp.src(src + '/*.jade')
.pipe(jade({ locals: {data: data}, pretty:true}))
.pipe(rename('intermediate.html'))
.pipe(gulp.dest(src));
})
/* ===== HTML ===== */
gulp.task('html', function() {
// Get file
return gulp.src('./src/intermediate.html')
.pipe(inlineCss({
applyStyleTags: true,
applyLinkTags: true,
removeStyleTags: true,
removeLinkTags: true
}))
.pipe(inject(gulp.src([src + '/responsive.css']), {
starttag: '<!-- inject:head:{{ext}} -->',
transform: function (filePath, file) {
// return file contents as string
return file.contents.toString('utf8')
}
}))
.pipe(rename('index.html'))
.pipe(minifyHTML(options))
// Output file
.pipe(gulp.dest(archive))
.pipe(gulp.dest(dest));
});
/* ===== WATCH ===== */
gulp.task('watch', function() {
// Folders to watch and tasks to execute
gulp.watch([src + '/template.jade'], ['default']);
});
/* ===== DEFAULT ===== */
// Default gulp task ($ gulp)
gulp.task('default', function(callback) {
runSequence('clean',
'templates',
'html',
'notify',
callback);
});
Now what happens when a build happens ?
file.jade outputs intermediate.html
but index.html is produced with the OLD intermediate.html version, before its produced by the jade template. It's a bit tricky to explain.
What I mean is I need to do 2 gulp in a row every time to get the up to date index.html ! Because index.html takes the intermediate.html version that exists BEFORE the template is compiled from jade. I hope I'm being clear enough
I thought it would be ok with a runsequence but it doesn't seem to be !
I'm not a pro but those returns look problematic. If you're doing asynchronous stuff you need to use callbacks. It is likely skipping over the return statements altogether, or running them after everything else.
gulp.task('html', function() {
// Get file
gulp.src('./src/intermediate.html')
.pipe(inlineCss({
applyStyleTags: true,
applyLinkTags: true,
removeStyleTags: true,
removeLinkTags: true
}))
.pipe(inject(gulp.src([src + '/responsive.css']), {
starttag: '<!-- inject:head:{{ext}} -->',
transform: function (filePath, file) {
// return file contents as string
file.contents.toString('utf8')
}
}))
.pipe(rename('index.html'))
.pipe(minifyHTML(options))
// Output file
.pipe(gulp.dest(archive))
.pipe(gulp.dest(dest));
});
Disclaimer: I've never used gulp.
Also, is your console printing any errors or warnings?
This is pretty much a Grunt construction where you output to disk and pick it up in another task. You want to keep these things in one stream without writing the intermediate to disk in Gulp.
Since it all sequential anyway, why not run it through one pipeline? Template and html should be combined into one gulp task imo. The author of Gulp also confirms this here: How can I pipe stream between tasks #69
If you really want the logic to be separated, you could use lazypipe to construct two pipes beforehand (or even return them from a utility).
Option 2
If you're adamant about keeping these tasks as two parts or files, you can write them as two gulp plugins and pipe from one to another. Though this seems overengineering to me, it's a possibility. How to write a gulp plugin.

Gulp Dependent Tasks

In order to build the final JS source for a web app, I am compiling JavaScript templates, CoffeScript sources and vanilla JS vendor scripts. A final task, dependent on the former three, would then concatenate the scripts together into one file.
The following setup, in which I define the last task with dependencies to the first three, the final step never executes. It seems that process doesn't wait until the partial files are written to the disc.
I tried merging event streams as well, but it seems to be an overkill for something like this. I'd appreciate if someone can point me in the right direction here.
// compile JS templates
gulp.task('js-build-template', function() {
gulp.src('./../app/assets/javascripts/**/*.jst.eco')
.pipe(eco({ basePath: 'app/assets/javascripts', namespace: 'JST_ATL' }))
.pipe(concat('_templates.js'))
.pipe(gulp.dest('public/assets/scripts/partials'));
});
// compile CoffeeScript source
gulp.task('js-build-source', function() {
gulp.src(js.source)
.pipe(coffee())
.pipe(concat('_source.js'))
.pipe(gulp.dest('public/assets/scripts/partials'));
});
// compile vendor scripts
gulp.task('js-build-vendor', function() {
gulp.src(js.vendor)
.pipe(concat('_vendor.js'))
.pipe(gulp.dest('public/assets/scripts/partials'));
});
// concatenate and fingerprint files
gulp.task('js-build', [ 'js-build-template', 'js-build-source', 'js-build-vendor' ], function() {
gulp.src([ 'public/assets/scripts/partials/_templates.js', 'public/assets/scripts/partials/_vendor.js', 'public/assets/scripts/partials/_source.js' ])
.pipe(concat('app.js'))
.pipe(gulp.dest('public/assets/scripts'))
.pipe(rev())
.pipe(gulp.dest('public/assets/scripts'))
.pipe(rev.manifest())
.pipe(gulp.dest('public/assets/scripts'));
});
in all 3 of your task you need return statements
gulp.task('js-build-template', function() {
return gulp.src('./../app/assets/javascripts/**/*.jst.eco')
.pipe(eco({ basePath: 'app/assets/javascripts', namespace: 'JST_ATL' }))
.pipe(concat('_templates.js'))
.pipe(gulp.dest('public/assets/scripts/partials'));
});
this will help in letting final task know that they have finished and it needs to start...

gulp reference to original source after minification

Once magnification is done, and let's say I had some bug,
and I want the console of browser to point me to original source so I could see the problem clearly instead of minified lines of code.
Script.js + many more files (concatenation plus minification)
var somevar = 4
console.log(someVar) //misspelled var name
console will take me to this file
script.min.js
var somevar=4;console.log(someVar)
I've seen some .map files with some js libraries, don't know how they work.
Can someone advise how can the console of a browser can refer to original source in case of an error /problem in a minified file.
gulp.task("app", function() {
var app = [
"js/libs/abc.js",
"js/file1.js",
"js/file2.js"
];
gulp.src(app)
.pipe(concat("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest("js"))
});
Install this to your dev dependencies
https://www.npmjs.com/package/gulp-sourcemaps
gulp.src(app)
.pipe(concat("app.min.js"))
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write("./"))
.pipe(gulp.dest("js"))
Make sure the generated JavaScript file, example.js, has the source mapping url at the end as follows:
//# sourceMappingURL=example.js.map

Display javascript error when using gulp

hi all i am using gulp uglify and concat to minify js code.
However, i would like to have a way to detect any coding error in the original dev js code so that i can check the original code and not only notified after minified.
May I know how can i do it?
Below is my gulp code.
gulp.task('frontend.js', function() {
return gulp.src([paths.dev.js + 'jquery.js', paths.dev.js + 'bootstrap.js', paths.dev.js + 'basic.js'])
.pipe(jsconcat('script.js'))
.pipe(uglify())
.pipe(gulp.dest(paths.assets.js)) // output: script.js
.pipe( notify({message: 'frontend.js converted'}));
});
That's what source maps are for.
var sourcemaps = require('gulp-sourcemaps');
gulp.task('frontend.js', function() {
return gulp.src([paths.dev.js + 'jquery.js', paths.dev.js + 'bootstrap.js', paths.dev.js + 'basic.js'])
.pipe(jsconcat('script.js'))
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write())
.pipe(gulp.dest(paths.assets.js)) // output: script.js
.pipe( notify({message: 'frontend.js converted'}));
});
It'll append source maps (i.e. mapping each minified line to the original line) to frontend.js.
Now if you're using a modern browser such as Chrome or Firefox you'll see the original code.
Introduction to source maps
How to use source maps in Chrome
Another gulp plugin
Do you mean that you want to be notified about javascript errors before concatenating and minifying your source files or that you want a way for being able to match a runtime error on the minified file with the original source file containing the offending code?
In the latter case mak answer if perfect, otherwise you should pipe, before the jsconcat, a call to gulp-jshint using maybe jshint-stylish as jshint reporter.

Categories