Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Browserify only if lint passes in Gulp

I'm trying to achieve this Gulp stream:

enter image description here

It seems like a fairly straight-forward process, but from what I can tell, it is not possible to implement as a Gulp stream.

I'm currently doing this:

gulp.task('js', function () {
    return browserify('foo/main.js')
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(streamify(jshint()))
        .pipe(jshint.reporter('default'))
        // source map, minify, …
});

The problem is that JSHint should run first, only on the changed file, and the process should be aborted if the lint fails. In my setup, Browserify always runs, and only then JSHint runs on the entire bundle. I can deal with the performance penalty, but the JSHint's line numbers correspond to the generated bundle, and not my JS source files, which is a pain.

like image 455
Šime Vidas Avatar asked Dec 27 '14 17:12

Šime Vidas


1 Answers

This is a cool idea. I've implemented this into my pipeline using watchify, which will lint files using the default reporter, and use the fail reporter if the file changed didn't pass the lint test. Even though this is recommended in the question, personally I would avoid doing this as what you really want is just for your reporter to emit lint checks, whilst keeping the development watcher still spawned in the background. Otherwise you have to keep restarting the task, which would generally tend to bug me. Anyway, here's the code:

'use strict';

var assign       = require('object-assign'),
    gulp         = require('gulp'),
    gutil        = require('gulp-util'),
    merge        = require('merge-stream'),
    jshint       = require('gulp-jshint'),
    source       = require('vinyl-source-stream'),
    watchify     = require('watchify'),
    browserify   = require('browserify');

var resources = {
    mainJS    : 'main.js',
    bundleJS  : 'bundle.js',
    root      : 'www'
};

function res(r) {
    return './' + resources[r];
}

gulp.task('watch', function() {
    var bundler = watchify(browserify(res('mainJS'), assign(watchify.args, {
        fullPaths: false
    })));

    var scripts = function(changedFiles) {
        var compileStream = bundler
            .bundle()
            .on('error', gutil.log.bind(gutil, gutil.colors.red('Browserify Error\n')))
            .pipe(source(res('bundleJS')))
            .pipe(gulp.dest(res('root')));

        if (changedFiles) {
            var lintStream = gulp.src(changedFiles)
                .pipe(jshint())
                .pipe(jshint.reporter('default'))
                .pipe(jshint.reporter('fail'));

            return merge(lintStream, compileStream);
        }

        return compileStream;
    };

    bundler.on('update', scripts);

    return scripts();
});

Note that this is based heavily off the official recipe for fast browserify builds with watchify (https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md), and is an 'all-in-one' type task; that is to say that I will generally spawn a single task somewhere off in the background, with minimal logging (I run gulp with the --silent flag), which is personally easier to deal with :-)

like image 119
Ben Avatar answered Sep 29 '22 03:09

Ben