Automation Features of GulpJS

Standard

 

  1. JS Code Style Guide and Analysis
  • Use this task in order to implement your javascript style guide and detect errors.
  • Highlight all rules in your .jshintrc and .jscsrc file.
  • Gulp will test javascript code from these files in order to enforce rules.

Sample Js Hint File

Sample Js Code Style File

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-load-plugins jshint-stylish gulp-util

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('jsCode', function () {
    return gulp
        .src('test/*.js')
        .pipe($.jscs())
        .pipe($.jshint())
        .pipe($.jshint.reporter('fail'));
    });

Execute:

    gulp jscode

 

 

2. less and sass compilation

  • Use gulp-less in order to compile less into css before browsing
  • Task will take care of variables, operators, functions, mixins etc in your less file
  • You may use AutoPrefixer to add vendor prefixes

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-less gulp-autoprefixer 

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('css', function () {
    return gulp
        .src('test/*.less')
        .pipe($.less())
        .pipe($.autoprefixer({ browsers: ['last 2 version', '> 5%'] }))
        .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp css

 

 

3. Add Javascript and CSS dynamically in main file

  • Use wiredep to inject bower js and css dependencies into index.html
  • Use gulp-inject to inject custom js and css dependencies into index.html

Pre Install:

    npm install --save-dev gulp gulp-load-plugins

Install:

    npm install --save-dev wiredep gulp-inject

Syntax in HTML File for wiredep:

    <!-- bower:css -->

    <!-- endbower -->

    <!-- bower:js -->

    <!-- endbower -->

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    var options = {
        bowerJson: require('./bower.json'),
        directory: './bower_components/',
        ignorePath:  '../..'
    }

    gulp.task('injectJS', function () {
        var wiredep = require('wiredep').stream;

        return gulp
            .src('./src/index.html')
            .pipe(wiredep(options))
            .pipe($.inject(gulp.src('modules/home/**/*.js')))
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp injectJS

Syntax in HTML File for gulp-inject:

    <!-- inject:css -->

    <!-- endinject -->

    <!-- inject:js -->

    <!-- endinject -->  

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('injectCSS', function () {

        return gulp
            .src('./src/index.html')
            .pipe($.inject(gulp.src('content/**/*.css')))
            .pipe(gulp.dest('./build/content/'));
    });

Execute:

    gulp injectCSS

 

 

4. Automatic Browser Refresh

  • Use BrowserSync to view live changes in html/JS/CSS to browser
  • Proxy attribute should have IIS path and port
  • Ghost Mode synchronize actions across browsers e.g. scroll, click etc

Browser Sync

Pre Install:

    npm install --save-dev gulp lodash node-notifier

Install:

    npm install --save-dev browser-sync

Code:

    var gulp = require('gulp');
    var browserSync = require('browser-sync');
    var _ = require('lodash');

    gulp.task('browser-sync', function () {
        if (browserSync.active) {
            return;
        }
        var options = {
            proxy: 'localhost:' + 3472,
            port: 3470,
            files: [
                './scripts/**/*.*'
            ],
            ghostMode: {
                clicks: true,
                location: false,
                forms: true,
                scroll: true
            },
            injectChanges: true,
            logFileChanges: true,
            logLevel: 'debug',
            logPrefix: 'gulp-patterns',
            notify: true,
            reloadDelay: 1000 
        };
        browserSync(options);
    });

    function notify(options) {
        var notifier = require('node-notifier');
        var notifyOptions = {
            sound: 'Bottle',
            contentImage: path.join(__dirname, 'gulp.png'),
            icon: path.join(__dirname, 'gulp.png')
        };
        _.assign(notifyOptions, options);
        notifier.notify(notifyOptions);
    }

Execute:

    gulp browser-sync   

 

 

5. Compressing Images

  • Use gulp-imagemin to minify PNG, JPEG, GIF and SVG images
  • Use optimizationLevel attribute to adjust compression between 0 and 7

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-imagemin 

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('images', function () {

        return gulp
            .src('./src/images/')
            .pipe($.imagemin({ optimizationLevel: 4 }))
            .pipe(gulp.dest('./build/images'));
    });

Execute:

    gulp images

 

 

6. Copy Files

  • For copying files like fonts, non-compressing images etc

Code:

    var gulp = require('gulp');

    gulp.task('delete', function () {

        return gulp
            .src('./src/fonts/')
            .pipe(gulp.dest('./build/fonts'));
    });

Execute:

    gulp delete

 

 

7. Delete Files

  • For deleting folders and files.

Install:

    npm install --save-dev del

Code:

    var gulp = require('gulp');
    var del = require('del');

    gulp.task('delete', function () {

        del('./build/');
    });

Execute:

    gulp delete

 

 

8. List all task Files

  • Use gulp-task-listing in order to list all tasks in your gulpjs file

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-task-listing 

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('help', $.taskListing);

Execute:

    gulp help

 

 

9. Caching HTML Templates

  • Use gulp-angular-templatecache in order to concatenates and registers AngularJS templates in the $templateCache
  • All HTML files will be stored as key-value pair using angular $templateCache service
  • URL of HTML will be key and html code of file will be value in $templateCache service
  • This will reduce HTTP requests
  • For each HTML request by angular, first it will check $templateCache service, If not found then it will make HTTP request for that HTML file
  • standAlone attribute in options means to make a new angular module for templates
  • gulp-angular-templatecache will create a file and using .run() service of main module, this will load all html in $templateCache service

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-angular-templatecache gulp-minify-html 

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var options =   {
                module: 'ModuleName',
                standAlone: false,
                root: 'scripts/app/'
            }   

    gulp.task('templatecache', function () {

        return gulp
            .src('**/*.html')
            .pipe($.minifyHtml({ empty: true }))
            .pipe($.angularTemplatecache(
                    'templates.js',
                    options
                ))
            .pipe(gulp.dest('./.tmp/'));
    });

Execute:

    gulp templatecache

 

 

10. Combing all JS and CSS into respective one file

  • Use gulp-useref in order to concatenate all css into one css file and all js files into one js file
  • Parse build blocks in HTML files to replace references to non-optimized scripts or stylesheets.
  • Similar to gulp-inject
  • Index.html should have bower/inject/build section, bower and inject area should be populated first using wiredep and gulp-inject task, then execute this task to concatenate all css and js file into respective single file as mentioned under build tag of index.html

Pre Install:

    npm install --save-dev gulp gulp-load-plugins

Install:

    npm install --save-dev gulp-useref@v1.1.0

Syntax in HTML File for gulp-useref:

    <!-- build:css content/lib.css -->
    <!-- bower:css -->
    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:css content/site.css -->
    <!-- inject:css -->
    <!-- inject -->
    <!-- endbuild -->

    <!-- build:js js/lib.js -->
    <!-- bower:js -->
    <!-- endbower -->
    <!-- endbuild -->

    <!-- build:js js/app.js -->
    <!-- inject:js -->
    <!-- endinject -->
    <!-- endbuild -->

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath: './' });

    gulp.task('combine', function () {

        return gulp
            .src('./build/index.html')
            .pipe(assets)
            .pipe(assets.restore())
            .pipe($.useref())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp combine
  • $.useref.assets() collects assets from the HTML comment
  • $.useref.restore() restore the files to the index.html
  • $.useref() will concatenate files

 

 

11. Minifying Files

  • Use gulp-Uglify to remove whitespace, comments, minify javascript files
  • Use gulp-CSSO to remove whitespace, comments, transform css files
  • Use gulp-filter to seperate out/reduce/filter files from gulp stream
  • Manglin your code can break angular dependency injection, in order to avoid this use Strict Dependency Injection (ng-strict-di) or $inject Property Annotation
  • Filter.restore() function put filter back into stream

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-filter@v2.0.0 gulp-csso gulp-uglify

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath:  './' });
    var cssFilter = $.filter('**/*.css');
    var jsFilter = $.filter('**/*.js');

    gulp.task('minify', function () {

        return gulp
            .src('./build/index.html')
            .pipe(assets)
            .pipe(cssFilter)
            .pipe($.csso())
            .pipe(cssFilter.restore())
            .pipe(jsFilter)
            .pipe($.uglify())
            .pipe(jsFilter.restore())
            .pipe(assets.restore())
            .pipe($.useref())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp minify 

 

 

12. Angular Dependency Injection

  • Use gulp-ng-annotate in order to provide automatic security blanket because manglin your code can break angular dependency injection
  • gulp-ng-annotate looks for dependency injection and adds angular injection
  • Use ** /* @ngInject / * annotation on top of controller, services, anonymous function etc to resolve dependency injection if forget to use Strict Dependency Injection (ng-strict-di) or $inject Property Annotation.
  • @ngInject provide code hint for gulp-ng-annotate to add angular injections
  • Avoid implementing @ngInject for third party libraries

Pre Install:

    npm install --save-dev gulp gulp-load-plugins

Install:

    npm install --save-dev gulp-ng-annotate

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var assets = $.useref.assets({ searchPath:  './' });
    var cssFilter = $.filter('**/*.css');
    var jsLibFilter = $.filter('**/' + config.optimized.lib);
    var jsAppFilter = $.filter('**/' + config.optimized.app);

    gulp.task('di', function () {

        return gulp
        .src('./build/index.html')
        .pipe(assets)
        .pipe(cssFilter)
        .pipe($.csso())
        .pipe(cssFilter.restore())
        .pipe(jsLibFilter)
        .pipe($.uglify())
        .pipe(jsLibFilter.restore())
        .pipe(jsAppFilter)
        .pipe($.ngAnnotate())
        .pipe($.uglify())
        .pipe(jsAppFilter.restore())
        .pipe(assets.restore())
        .pipe($.useref())
        .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp di

 

 

13. Revisions

  • Use gulp-rev in order to implement static asset revisioning by appending content hash to filenames: unicorn.css => unicorn-d41d8cd98f.css
  • Use gulp-rev-replace in order to rewrite occurences of filenames which have been renamed by gulp-rev in index.html(html referencing file)
  • gulp-rev-replace solves the cache problem too

Pre Install:

    npm install --save-dev gulp gulp-load-plugins 

Install:

    npm install --save-dev gulp-rev gulp-rev-replace

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });

    gulp.task('revision', function () {

        return gulp
            .src('src/*.js')
            .pipe($.rev())
            .pipe(gulp.dest('./build/'));
    });

Execute:

    gulp revision

 

 

14. File Version

  • Use gulp-bump for vesrioning in package.json and bower.json
  • –type=pre will bump the prerelease version ..*-x
  • –type=patch or no flag will bump the patch version ..x
  • –type=minor will bump the minor version .x.
  • –type=major will bump the major version x..
  • –version=1.2.3 will bump to a specific version and ignore other flags
  • for –version=1.2.3 means 1 corresponds to major, 3 corresponds to minor and 3 corresponds to package version

Pre Install:

    npm install --save-dev gulp gulp-load-plugins yargs

Install:

    npm install --save-dev gulp-bump

Code:

    var gulp = require('gulp');
    var $ = require('gulp-load-plugins')({ lazy: true });
    var args = require('yargs').argv;

    gulp.task('version', function () {
        var type = args.type;
        var version = args.version;
        var options = {};
        if (version) {
            options.version = version;
        } else {
            options.type = type;
        }
        return gulp
            .src([ './package.json', './bower.json' ])
            .pipe($.bump(options))
            .pipe(gulp.dest('./'));
    });

Execute:

    gulp version --version=2.0.0
    gulp version --type=minor

 

 

15. Unit Testing with Jasmine and Karma

  • karma is Test Runner for JavaScript, a tool that allows you to execute JS code in multiple real browsers
  • karma is A Karma plugin. used to generate code coverage.
  • Task singleRun refers to execute tests once, it can fail a build but perfect for continuous integration
  • Task alwaysRun refers to execute tests and stay alive, monitors changes in file and re-run with each change
  • Please make sure karma.config.js file is included in your project before executing gulp task
  • __dirname is global object of NodeJS for the name of the directory that the currently executing script resides in

Pre Install:

    npm install --save-dev gulp

Install:

    npm install --save-dev karma phantomjs karma-coverage karma-growl-reporter karma-phantomjs-launcher  karma-firefox-launcher karma-ie-launcher karma-chrome-launcher karma-jasmine jasmine

Code:

    var gulp = require('gulp');

    gulp.task('singleRun', function (done) {
        startTests(true, done);
    });

    gulp.task('alwaysRun',  function (done) {
        startTests(false, done);
    });

    function startTests(singleRun, done) {
        var karma = require('karma').server;
        var excludeFiles = [];
        var serverSpecs = 'tests/**/*.spec.js'

        karma.start({
            configFile: __dirname + '/karma.config.js',
            exclude: excludeFiles,
            singleRun: !!singleRun
        }, karmaCompleted);

        function karmaCompleted(karmaResult) {
            if (karmaResult === 1) {
                done('karma: tests failed with code ' + karmaResult);
            } else {
                done();
            }
        }
    }

Execute:

    gulp singleRun
    gulp alwaysRun

 

 

16. E2E Testing with Protractor

  • Protractor is an end-to-end test framework for AngularJS applications
  • It execute tests against your application running in a real browser, interacting with it as a real life user.
  • Make sure you have updated version of webdriver-manager otherwise execute below command in cmd before executing gulp task
webdriver-manager update --standalone
  • In protractor.config.js file mention file path to the selenium server jar, path of chrome driver and comment out address of a running selenium server before executing gulp task

 

seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.48.2.jar',
chromeDriver: './node_modules/protractor/selenium/chromedriver.exe',
//seleniumAddress: 'http://localhost:4444/wd/hub',
  • Start webdriver-manager in seperate console before executing gulp task
webdriver-manager start
  • __dirname is global object of NodeJS for the name of the directory that the currently executing script resides in

Pre Install:

    npm install --save-dev gulp

Install:

    npm install --save-dev gulp-protractor protractor

Code:

    var gulp = require('gulp');
    var protractor = require("gulp-protractor").protractor;

    gulp.task('e2e', function (done) {
        gulp.src(__dirname + './protractor_test/')
        .pipe(protractor({
            configFile: './protractor.config.js',
            args: ['--baseUrl', 'http://127.0.0.1:8000']
        }))
        .on('error', function (e) { throw e })
    });

Execute:

    gulp e2e

 

 

17. Setting up test runner on HTML

  • Use gulp-jasmine-browser in order to execute jasmine tests in a browser using gulp.
  • In order to check output, type following url in browser window: http://localhost:8888/

Pre Install:

    npm install --save-dev  

Install:

    npm install --save-dev gulp-jasmine-browser

Code:

    var gulp = require('gulp');
    var jasmineBrowser = require('gulp-jasmine-browser');
    var config.files = ['./scripts/lib/angular/angular.js',
        './scripts/lib/angular/angular-mocks.js',
        './scripts/app/myService.services.js',
        './scripts/app/myService.services-spec.js',];

    gulp.task('jasmineBrowser', function () {
        return gulp.src(config.files)
          .pipe(jasmineBrowser.specRunner())
          .pipe(jasmineBrowser.server({ port: 8888 }));
    });

Execute:

    gulp jasmineBrowser

 

Leave a comment