What is grunt?

You surely know all these monotonous

 and tiresome tasks

 

  • Setup local server
  • Minify files
  • Concat files
  • Run Bower install
  • Run NPM install
  • Compile Sass
  • Lint your JavaScript
  • Minify pictures
  • Make a build or production folder
  • Add your javascript files to index.html

Grunt to the resque

Grunt is: "In one word: automation. The less work you have to do when performing repetitive tasks the easier your job becomes. After you've configured it through a Gruntfile, a task runner can do most of that mundane work for you—and your team—with basically zero effort."

Install Grunt

Grunt requires:

  1. Node.js (>= 0.8.0)
  2. NPM (npm update -g npm)

To get started you need to install grunt globaly as a comand line interface

npm install -g grunt-cli

The 'grunt' command is now available in your system,  to be run from any directory

Npm uses package.json to track the projects npm modules. Grunt and its plugins are listed there as devDependencies

cd to/your/project

npm init

The init command will ask some questions, and creates package.json for your project.

Till now we have not installed the actual grunt task runner. Only its command line Interface. 

The CLI makes it possible to have different versions of grunt on separate projects.  

npm install grunt --save-dev

Whit this command you add grunt to your project. 

Create a Gruntfile.js or Gruntfile.coffee in your projects root directory

In the Gruntfile you'll find:

  1. The "wrapper" function
  2. Project and task configuration
  3. Loading Grunt plugins and tasks *
  4. Custom tasks

Every Gruntfile uses a "wrapper" function, and all of your Grunt code must be specified inside this function

module.exports = function(grunt) {
  // Do grunt-related things in here
};

Make a grunt.initConfig methode to configurate  your grunt tasks

// Project configuration.
grunt.initConfig({
  // your task configurations go here
});

Grunt and every grunt plugin need to be enabled in your gruntfile. 

 

// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');

You don't always need to run all the tasks you added to the Gruntfile at once.

Therefor you can make custom tasks to run only a specific set of tasks when you type that command in the command line

//  Task(s).
grunt.registerTask('serve', [
    //specific tasks to run the localhost
    //grunt serve
]);

grunt.registerTask('build', [
    //specific tasks to run to make a build
    //grunt build
]);

grunt.registerTask('test', [
    //specific tasks to run for testing
    //grunt test
]);
  • * matches any number of characters, but not /
  • ? matches a single character, but not /
  • ** matches any number of characters, including /, as long as it's the only thing in a path part
  • {} allows for a comma-separated list of "or" expressions
  • ! at the beginning of a pattern will negate the match

As I said before there is a task to enable grunt and all your grunt plugins at once

npm install load-grunt-tasks --save-dev 
// Gruntfile.js
module.exports = function(grunt) {
    // load all grunt tasks based on globbing patterns
    require('load-grunt-tasks')(grunt);

    grunt.initConfig({});
    grunt.registerTask('default', []);
};

Start a connect web server

npm install grunt-contrib-connect --save-dev
// Gruntfile.js

grunt.initConfig({
  connect: {
    server: {
      options: {
        port: 6001,
        base: './',
        livereload: false,
        open: {
          target: 'http://localhost:6001'
        }
      }
    }
  },
});

Run predefined tasks whenever watched file patterns are added, changed or deleted.

npm install grunt-contrib-watch --save-dev
// Gruntfile.js

grunt.initConfig({
    watch: {
      options: {
        livereload: true,
      },
      css: {
        files: '**/*.sass',
        tasks: ['sass'],

      },
    }
});

Validate files with JSHint and JSHint-stylish

npm install grunt-contrib-jshint --save-dev
npm install jshint-stylish --save-dev 
// Project configuration. 
grunt.initConfig({
  jshint: {
    options: {
      reporter: require('jshint-stylish')
    },
    all: [
      'Gruntfile.js', 
      'lib/**/*.js', 
      'test/**/*.js'
    ]
  }
});

Compile Sass to CSS


npm install grunt-contrib-sass --save-dev
// Project configuration. 
grunt.initConfig({
    sass: {
      dist: {
        files: {
          'css/style.css': 'scss/*.scss'
        }
      }
    },
});

This task requires you to have Ruby and Sass installed.

Validate html files with htmlhint.

npm install grunt-htmlhint --save-dev
// Project configuration. 
grunt.initConfig({
    htmlhint: {
      build: {
        options: { // check options
          'tag-pair': true,
          'tagname-lowercase': true,
          'attr-lowercase': true,
          'attr-value-double-quotes': true,
          'doctype-first': false,
          'spec-char-escape': true,
          'id-unique': true,
          'head-script-disabled': true,
          'style-disabled': true
        },
        src: ['index.html', 'templates/**/*.html']
      }
    },
});

Grunt task to install npm modules.​

npm install grunt-htmlhint --save-dev

No further configurations needed

Install Bower packages.

npm install grunt-bower-task --save-dev
// Project configuration. 
grunt.initConfig({
  bower: {
    options: {
      targetDir: 'bower_components'
    },
    install: {}
  },
});

Inject your Bower dependencies right into your HTML from Grunt.

npm install --save-dev grunt-wiredep
// Project configuration. 
grunt.initConfig({
  wiredep: {
    app: {
      src: ['source/index.html'],
    }
  },
});
//index.html
<!-- bower:js -->
<!-- endbower -->

Add flag comments in your index.html to indicate the place where you want to inject the script tags.

Autoinsert script tags in an html file

npm install grunt-sails-linker --save-dev
// Project configuration. 
grunt.initConfig({
  'sails-linker': {
    defaultOptions: {
      options: {
        startTag: '<!--SCRIPTS-->',
        endTag: '<!--SCRIPTS END-->',
        fileTmpl: '<script src="%s"></script>',
        appRoot: 'source/'
      },
      files: {
        'source/index.html': ['source/js/**/*.js']
      }
    }
  },
});
//index.html
<!-- SCRIPTS -->
<!-- SCRIPTS END -->

Add flag comments in your index.html to indicate the place where you want to inject the script tags.

Copy files and folders

npm install grunt-contrib-copy --save-dev
// Project configuration. 
grunt.initConfig({
  copy: {
    main: {
      src: 'src/*',
      dest: 'dest/',
    },
  },
});

Concatenate files.

npm install grunt-contrib-concat --save-dev
// Project configuration. 
grunt.initConfig({
  concat: {
    options: {
      separator: ';',
    },
    libraries: {
      src: ['./bower_components/{,*/}*.js', '!./bower_components/{,*/}*min.js'],
      dest: 'build/js/vendor.js',
    },
    customJS: {
      src: ['source/js/{,*/}*.js' ],
      dest: 'build/js/main.js',
    },
  },
});

Minify javascript files with UglifyJS

npm install grunt-contrib-uglify --save-dev
// Project configuration. 
grunt.initConfig({
  uglify: {
    build: {
      files: {
          'build/js/vendor.min.js': ['build/js/vendor.js'],
          'build/js/main.min.js': ['build/js/main.js']
      }
    }
  },
});

Process html files at build time to modify them depending on the release environment

npm install grunt-processhtml --save-dev
// Project configuration. 
grunt.initConfig({
  processhtml: {
    build: {
      files: {
        'build/index.html' : ['source/index.html']
      }
    }
  },
});
//index.html
<!-- build:js build/js/vendor.min.js -->
  <!-- bower:js -->
  <!-- endbower -->
<!-- /build -->

<!-- build:js build/js/main.min.js -->
  <!-- SCRIPTS -->
  <!-- SCRIPTS END -->
<!-- /build -->

Clean files and folders

npm install grunt-contrib-clean --save-dev
// Project configuration. 
grunt.initConfig({
 clean: {
   beforeBuild: {
     src: [
       'build'
     ]
   },
   afterBuild: {
     src: [
      'build/js/{,*/}*.js',
      '!buld/js/main.min.js',
      '!build/js/vendor.min.js',
     ]
   }
 },
});

Resources

Grunt

By tietyk

Grunt

Basic setup of grunt and gruntfile implementation with my most used plugins

  • 1,535