grunt-js

What is grunt?

Does things

Minify
(JS, CSS)
Validate
(JSHint)
Compile
(Sass, Compass, LESS)
Test
(Jasmine)
Copy
Clean
Rename
Publish
You name it…

"Task Runner"



Ummm… build???

"Task Runner"

With plugins

In node.js
(JavaScript on the server)

Lots of plugins


gruntjs.com/plugins

Search for contrib for core plugins

Plugins

  • Minify
  • Validate
  • Compile
  • Test
  • Copy
  • Clean
  • Rename
  • Publish
  • etc.

How?

Gruntfile.js

3 sections

  1. Configure
  2. Load Plugins
  3. Define Tasks

Define Tasks

						
  grunt.registerTask('default', ['clean', 'copy', 'build-index']);
  grunt.registerTask('publish', ['default', 'gh-pages']);
						
					

Type "grunt", the default task will run.


"grunt publish" will run default followed by the gh-pages task.

Load Plugins

						
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-gh-pages');
  grunt.loadNpmTasks('grunt-contrib-clean');
						
					

Each Task is given a name. In this case:

  • copy
  • gh-pages
  • clean


The task name is usually obvious. Documentation will always tell you.

E.g. the gh-pages task documentation

Configure

						
  grunt.initConfig({
    clean: {
      src: 'build/'
    },
    copy: {
      main: {
        src: '**/*',
        dest: 'build/'
      },
      gitignore: {
        src: '.gitignore',
        dest: '<%= copy.main.dest %>'
      }
    },
    'build-index': {
      src: 'index.tmpl',
      dest: '<%= copy.main.dest %>index.html',
      files: '<%= copy.main.src %>'
    },
    'gh-pages': {
      options: {
        base: 'build',
        dotfiles: true
      },
      src: '**/*'
    }
  });
						
					

Wrap it up…

						
module.exports = function(grunt) {
  // Define Tasks, Load Plugins and Configure
};
						
					

src & dest

						
  grunt.initConfig({
    copy: {
      main: {
        src: '**/*',
        dest: 'build/'
      }
    }
  });
						
					

Built-in

Easy file-sets

Plugins

gruntjs.com/configuring-tasks

Multi Tasks

Multi tasks may have >1 targets:
						
  grunt.initConfig({
    copy: {
      main: {
        src: '**/*',
        dest: 'build/'
      },
      gitignore: {
        src: '.gitignore',
        dest: '<%= copy.main.dest %>'
      }
    }
  });
						
					
Each target processed in turn

"Macros/Templates"

						
  grunt.initConfig({
    copy: {
      main: {
        src: '**/*',
        dest: 'build/'
      }
    },
    'build-index': {
      src: 'index.tmpl',
      dest: '<%= copy.main.dest %>index.html',
      files: '<%= copy.main.src %>'
    }
  });
						
					

<%= ... %>

inline config references

Options

						
  grunt.initConfig({
    'gh-pages': {
      options: {
        base: 'build',
        dotfiles: true
      },
      src: '**/*'
    }
  });
						
					

Task-specific options, again described in the documentation.

File Filters

						
  grunt.initConfig({
    exclusions: ['build','node_modules'],
    copy: {
      main: {
        src: '**/*',
        dest: 'build/',
        filter: function(filepath) {
          var filepathParts = filepath.split(require('path').sep);
          // We will copy all folders except those in the "exclude" 
          // property (build and node_modules)
          var shouldExclude = 
              (filepathParts.length === 1 && grunt.file.isFile(filepath)) ||
              (grunt.config('exclusions').indexOf(filepathParts[0]) !== -1);
          if (!shouldExclude) {
            // Log what we're copying with some debug info
            grunt.verbose.writeln('Including ' + filepath + ' ' + 
                                  filepath.split(require('path').sep)[0]);
          }
          return !shouldExclude;
        }
      }
    }
  });
						
					

NodeJS fs.Stats method name (e.g. "isDir" or "isFile")

…or custom function

Debug



I don't know.

No, really, I don't know. I'll get back to you on this

Custom Tasks

Already seen… Load

								
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-gh-pages');
  grunt.loadNpmTasks('grunt-contrib-clean');
								
							

Register

								
  grunt.registerTask('default', ['clean', 'copy', 'build-index']);
  grunt.registerTask('publish', ['default', 'gh-pages']);
								
							

copy, gh-pages, clean, default, publish, build-index(??)

Custom Tasks

						
  grunt.registerTask('build-index', 
                     'Generate index.html depending on configuration', 
                     function() {    
    // Read the config and read the template file.
    var conf = grunt.config('build-index'),
    tmpl = grunt.file.read(conf.src);

    // Process the template.
    grunt.file.write(conf.dest, grunt.template.process(tmpl));

    grunt.log.writeln('Generated \'' + conf.dest + '\' from \'' + conf.src + '\'');
  });

    // ... Remember the config was:
    'build-index': {
      src: 'index.tmpl',
      dest: '<%= copy.main.dest %>index.html',
      files: '<%= copy.main.src %>'
    }
						
					

Like "default" but with different parameters

							
	  grunt.registerTask('default', ['clean', 'copy', 'build-index']);
							
						

Installation

Install globally:
						
							npm install -g grunt-cli
						
					


To add to a project:
							
								npm install grunt --save
							
						

--save will add grunt to your package.json's dependencies section.

E.g. The 100-lines-or-less-builder package.json

Installing Plugins

To loadNpmTasks()…
								
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-gh-pages');
  grunt.loadNpmTasks('grunt-contrib-clean');
								
							
list plugin in package.json:
						{
  "name": "100-lines-or-less-js",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-copy": "*",
    "grunt-gh-pages": "~0.9.0",
    "grunt-contrib-clean": "~0.5.0"
  }
}
						
					

Again, can add using --save-dev npm option

End result

Gruntfile.js

gruntjs.com/getting-started

gruntjs.com/plugins

gruntjs.com/configuring-tasks