Can gulp-uglify strip out console.log statements? - gulp

As the question states. I know gulp-uglify can uglify with a simple:
gulp.src('filename')
.pipe(uglify())
Is there a way to tell it to strip out console.log statements too?

Yes there is!
As gulp-uglifyjs documentation mentions you can pass extra options ( gulp-uglifyjs documentation):
uglify([filename], [options])
All available options can be found on the compressor UglifyJS documentation page. From that 'drop_console: true' should help:
uglify([filename], {
compress: {
drop_console: true
}
})

Much better still: you can use the specialized gulp plugin: gulp-strip-debug. It doesn't only strip out console statements, but also alerts and debugger statements.
Strip console, alert, and debugger statements from JavaScript code with strip-debug
install it using:
npm install --save-dev gulp-strip-debug
and use it like:
var gulp = require('gulp');
var stripDebug = require('gulp-strip-debug');
gulp.task('default', function () {
return gulp.src('src/app.js')
.pipe(stripDebug())
.pipe(gulp.dest('dist'));
});

With gulp-uglify (not gulp-uglifyjs) you can remove arbitrary code by using a strategy similar to compilations constants with the compression configuration (Link goes to gulp-uglifyjs, but should be the same for gulp-uglify):
.pipe(uglify({
compress: {
global_defs: {
"DEBUG": false
}
}
}))
And then in your code write something like
if (DEBUG)
{
console.log("Application started...");
//...
}
if you set DEBUG in global_defs to true, gulp-uglify will remove the conditional but leave the inner branch. In case DEBUG is set to false, it will remove both.
drop_console as in Fill's answer does not seem to be supported in gulp-uglify.

Related

How can I check to see if a task is ran as a dependency of another task in gulp#4?

I use gulp-notify to trigger notifications when tasks complete. If a task is ran standalone, a notification for that specific task is triggered. If a task is ran as a dependency of another task, a notification for all dependencies is triggered.
In gulp#3, I check if the task is being called as a dependency using gulp.seq, which contains an array of the tasks being ran. Let's say I have three tasks: default, styles, and scripts, with the later two set as dependencies of the first. When running gulp styles, gulp.seq will contain [ 'styles' ]. When running gulp (the default task), gulp.seq will contain [ 'styles', 'scripts', 'default' ]. Knowing that, I then check gulp.seq.indexOf("styles") > gulp.seq.indexOf("default"), which tells me weather or not styles was ran as part of the default task.
With gulp#4, it appears that gulp.seq no longer exists. I've tried digging through the documentation and source code with no luck. It seems like gulp.tree({ deep:true }) (docs) might be what I'm looking for, but I don't see anything in it that returns anything useful.
Is there an equivalent of gulp.seq in gulp#4?
The API gulp.seq was never an official prop exposed by Gulp. With Gulp 4, you cannot do that. gulp.tree({ /* */ }) will not solve this problem for you.
Having said that, if you still need to find whether a task has run during some other task's pipeline, then you will have to decorate every gulp task with your own wrapper using something like this:
let runTasks = [];
function taskWrapper(taskName, tasks, thisTask) {
let callbackTask;
function innerCallback(cb) {
runTasks.push(taskName);
cb();
}
if (thisTask) {
callbackTask = function(cb) {
thisTask(function () {
innerCallback(cb);
});
}
} else {
callbackTask = innerCallback;
}
const newTasks = [ ...tasks, callbackTask ];
gulp.task(taskName, gulp.series(newTasks));
}
// INSTEAD OF THIS
// gulp.task('default', gulp.series('style', 'script', function () { }));
// DO THIS
taskWrapper('default', ['style', 'script'], function(cb) {
console.log('default task starting');
cb();
});
NOTE: Above code snippets has limitation. If you use watch mode, array maintaining the executed tasks i.e. runTasks will keep on growing. Also, it assumes tasks will always run in series. For a parallel mode, the logic gets little complicated.
Finally, you can also have a predefault task to help it further:
taskWrapper('predefault', [], function(cb) {
// RESET runTasks
runTasks = [];
cb();
});
taskWrapper('default', ['predefault', 'style', 'script'], function(cb) {
console.log('default task starting');
cb();
});
Also, I am doubtful if gulp-notify will work with Gulp 4.
Through a bit of luck, I discovered this was possible via the module yargs, which I already have installed.
When running gulp styles, for example, I can check argv._.indexOf("styles") > -1, as it contains ['styles']. When running gulp (i.e the default task), it contains []. In my testing, this works perfectly for my use case.

gulp postcss-simple-vars throws error at // comments

I'm attempting to migrate from Sass to postCSS and testing out postcss-simple-vars gulp plugin.
I'm using Webstorm IDE, which automatically uses javascript style comments (//) in .scss files, so my non-block comments are all // comments, not /* */.
postcss-simple-vars throws errors at all // comments, even with the silent option set to true.
Here's my gulp task:
gulp.task('postcss', function () {
return gulp
.src('./styles/sass2/*.scss')
.pipe($.postcss(
[
vars({
silent: true,
variables: colors
})
]))
.pipe(gulp.dest('./dest'));
});
Am I missing something really obvious? Is there some way to get postcss-simple-vars to ignore // style comments?
HOW I SOLVED IT:
I replaced all the // comments with /* */ comments with gulp-replace ($.replace).
gulp.task('replace-comments', function() {
return gulp
.src(config.scss)
.pipe($.replace(/\/\/.*/g, function(comment){
return '/*' + comment.substring(2) + ( '*/');
}))
.pipe(gulp.dest('./styles/sass3'));
});
The problem is not in postcss-simple-vars. It's that the default parser for postcss expects standard CSS, and // comments are not standard: they break the parser.
To run uncompiled SCSS with // comments through postcss, you should use the alternate parser postcss-scss. The documentation in that README and for gulp-postcss should explain how to use it.

Source Maps with Gulp, Browserify, Babel, ES6, and React

I am using Gulp with Browserify, and Babelify for ES6 and JSX-React transpiling. Despite numerous examples online, I can't figure out how to generate source-maps that point to the original pre-transpiled ES6/JSX files.
Here is my current gulp browserify task, which is based on this example:
gulp.task('browserify', function() {
browserify({ entries: './src/js/main.jsx', extensions: ['.jsx'], debug: true })
.transform(babelify, {presets: ["es2015", "react"]})
.bundle()
.pipe(source('main.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist/js'));
});
All this does is create a main.js.map file that seems to have the exact same content as the bundled main.js file. In Chrome it looks like this:
But I want to debug the original source .jsx and .js (with ES6 syntax) files. They look like this in my IDE:
How can I do this?
Add sourcemaps:true to babelify options
{presets: ["es2015", "react"],sourcemaps:true}
I simply had to change the settings in webpack.config.js
{
devtool: 'source-map', // Or some other option that generates the original source as seen from https://webpack.github.io/docs/configuration.html#devtool
...
}
You don't have to modify the sourceMap query param in Babel Loader because it is inferred from the devtool option of the Webpack config.

gulp-sourcemaps with gulp-minify-css crashes

I'm compiling bootstrap-sass with the gulp task:
gulp.task('build-bootstrap-sass', function () {
return gulp.src('styles/styles.sass')
.pipe(sourcemaps.init())
.pipe(sass({includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/']}).on('error', sass.logError))
.pipe(rename({basename:'bootstrap'}))
.pipe(autoprefixer())
.pipe(minifyCss())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist/' ));
});
But this gives me the following error:
[09:32:38] Using gulpfile d:\Code\Templates\App\gulpfile.js
[09:32:38] Starting 'build-bootstrap-sass'...
d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\escape-store.js:49
var index = this.restoreMatcher.exec(placeholder)[1];
^
TypeError: Cannot read property '1' of null
at EscapeStore.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\escape-store.js:49:52)
at UrlsProcessor.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\text\urls-processor.js:61:35)
at Object.restore (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\clean.js:195:28)
at store (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\source-maps.js:12:21)
at value (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:102:5)
at property (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:91:5)
at body (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:77:5)
at all (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\helpers.js:140:9)
at stringify (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\stringifier\source-maps.js:74:3)
at SelectorsOptimizer.process (d:\Code\Templates\App\node_modules\gulp-minify-css\node_modules\clean-css\lib\selectors\optimizer.js:20:10)
The issue seems to be when I use sourcemaps; If I remove it, the task passes. But I'm on the "latest" version for all my gulp dependencies; and the gulp-minify-css changelog indicates it got support for sourcemaps < 1.1.6.
The build also passes when I use sourcemaps without minify.
gulp-sourcemaps does not support gulp-minify-css.
You can find all supported plugins here: https://github.com/floridoo/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support
You could consider using gulp-cssnano for minifying css files.

Control order of source files

I'm using Gulp and the main-bower-files to bundle my bower dependencies.
I need to ensure that jQuery is included before AngularJS, but since the Angular bower package does not actually depend on jQuery it is included after.
Is there a way to push jQuery to the top of source list or override Angular's dependency so it does require jQuery?
I tried using the gulp-order plugin to do this but it messes up the original order of the remaining files:
gulp.task('bower', function () {
var sources = gulp.src(mainBowerFiles(['**/*.js', '!**/*.min.js'])); // don't include min files
return sources
// force jquery to be first
.pipe(plugins.order([
'jquery.js',
'*'
]))
.pipe(plugins.sourcemaps.init())
.pipe(plugins.concat('libs.min.js'))
.pipe(plugins.uglify())
.pipe(plugins.sourcemaps.write('./'))
.pipe(gulp.dest(config.output))
.pipe(plugins.notify({ message: 'Bower task complete' }));
});
You can override angulars dependencies in your project bower.json:
https://github.com/ck86/main-bower-files#overrides-options
{
...
"overrides": {
"angular": {
"dependencies": {
"jquery": "~1.8"
}
}
}
}
I haven't used main-bower-files but one trick I can think of is to just include the jquery file directly and don't load it in the main bower files array, e.g.
var glob = ['/path/to/jquery.js'].concat(mainBowerFiles(['**/*.js', '!/path/to/jquery.js']));
var sources = gulp.src(glob);