Grunt watch task running and compiling Foundation projects JS and CSS files

Foundation,Libsass and Grunt enhanced

I had to put up a quick front-end project today and, being still very far from confident when it comes to front-end, I’ve “stood on the shoulders of the giants” and employed Foundation 5 framework.
Following the instructions I’ve been happy to find out that a grunt managed installation is possible: following the “Libsass & Grunt” path will make the front-end part of the project feature a simple Gruntfile in the root folder

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    sass: {
      options: {
        includePaths: ['bower_components/foundation/scss']
      },
      dist: {
        options: {
          outputStyle: 'compressed'
        },
        files: {
          'css/app.css': 'scss/app.scss'
        }        
      }
    },

    watch: {
      grunt: { files: ['Gruntfile.js'] },

      sass: {
        files: 'scss/**/*.scss',
        tasks: ['sass']
      }
    }
  });

  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('build', ['sass']);
  grunt.registerTask('default', ['build','watch']);
}

and while that works I’d like to take some functions over from my grunt-init WordPress plugin template to have grunt do some more heavy lifting for me.

More gadgets

I’ve modified the original Gruntfile to pack more gadgets to this

// file Gruntfile.js

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        concat: {
            options: {
                stripBanners: true
            },
            app: {
                src: [
                    'js/src/app.js'
                ],
                dest: 'js/app.js'
            }
        },
        jshint: {
            all: [
                'Gruntfile.js',
                'js/src/app.js'
            ],
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                boss: true,
                eqnull: true,
                globals: {
                    exports: true,
                    module: false
                }
            }
        },
        uglify: {
            all: {
                files: {
                    'js/app.min.js': ['js/app.js']
                },
                options: {
                    mangle: {
                        except: ['jQuery']
                    }
                }
            }
        },
        test: {
            files: ['js/test/**/*.js']
        },

        libsass: {
            all: {
                options: {
                    includePath: ['bower_components/foundation/scss'],
                    outputStyle: 'compressed'
                },
                files: {
                    'css/app.css': 'scss/app.scss'
                }
            }
        },

        cssmin: {
            options: {
                banner: '/*! <%= pkg.title %> - v<%= pkg.version %>\n' +
                    ' * <%= pkg.homepage %>\n' +
                    ' * Copyright (c) <%= grunt.template.today("yyyy") %>;' +
                    ' * Licensed GPLv2+' +
                    ' */\n'
            },
            minify: {
                expand: true,
                cwd: 'css/',
                src: ['app.css'],
                dest: 'css/',
                ext: '.min.css'
            }
        },
        autoprefixer: {
            all: {
                options: {
                    browsers: ['last 2 versions']
                },
                src: 'css/app.css',
                dest: 'css/app.css'
            }
        },
        watch: {
            sass: {
                files: ['scss/*.scss'],
                tasks: ['sass', 'autoprefixer:all', 'cssmin'],
                options: {
                    debounceDelay: 500
                }
            },
            scripts: {
                files: ['Gruntfile.js', 'js/src/app.js'],
                tasks: ['jshint', 'concat', 'uglify'],
                options: {
                    debounceDelay: 500
                }
            }
        }
    });

    // Load other tasks
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin'); 
    grunt.loadNpmTasks('grunt-libsass'); 
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-autoprefixer');

    // Default task.

    grunt.registerTask('build', ['jshint', 'concat', 'uglify', 'sass', 'autoprefixer', 'cssmin']); 
    grunt.registerTask('default', ['watch', 'build']);

    grunt.util.linefeed = '\n';
};

which is in turn fed npm modules by a modified package.json file

// file package.json

{
  "name": "foundation-libsass-template",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "*",
    "grunt-contrib-concat": "*",
    "grunt-contrib-uglify": "*",
    "grunt-contrib-cssmin": "*",
    "grunt-contrib-jshint": "*",
    "grunt-contrib-nodeunit": "*",
    "grunt-contrib-watch": "*",
    "grunt-libsass": "*",
    "grunt-autoprefixer": "*"
  }
}

and will have to work on the js/src/app.js file in place of working on js/app.js file directly to change JavaScript code.
I’m pretty satisfied with the result and know it can be tweaked even further to specific project needs.

I appreciate your input