Book Image

Grunt Cookbook

By : Jurie-Jan Botha
Book Image

Grunt Cookbook

By: Jurie-Jan Botha

Overview of this book

<p>A web application can quickly turn into a complex orchestration of many smaller components, each one requiring its own bit of maintenance. Grunt allows you to automate all the repetitive tasks required to get everything working together by using JavaScript, the most popular programming language.</p> <p>Grunt Cookbook offers a host of easy-to-follow recipes for automating repetitive tasks in your web application's development, management, and deployment processes. This book will introduce you to methods that can be used to automate basic processes and your favorite tools. By following the recipes, you will soon be comfortable using Grunt to perform a wide array of advanced tasks in a range of different scenarios.</p>
Table of Contents (17 chapters)
Grunt Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Watching files for changes


Another common requirement for development environments is the need to automatically run specific tasks when certain files are changed. This is especially useful when you'd like to monitor the quality of changing code in real time, or recompile altered resources as soon as they change, so that the effect of the changes are reflected without any manual intervention.

The contirb-watch (0.6.1) plugin allows us to keep a watch on a specific set of files, and run a specified set of tasks when file events are observed.

Getting ready

In this example, we'll work with the basic project structure that we created in the Setting up Grunt on a project recipe of this chapter. Be sure to refer to it if you are not yet familiar with it's contents.

How to do it...

The following steps take us through setting up a watch task that initiates a code quality analysis on a JavaScript source file each time a change to the file is observed.

  1. We'll start by installing the package that contains the contrib-watch plugin and loading its tasks by following the instructions provided in the Installing a Plugin recipe of this chapter.

  2. For our example, we'll make use of the jshint task to analyze the quality of a JavaScript source file. Let's install the contrib-jshint plugin and load its tasks by following the instructions provided in the Installing a Plugin recipe of this chapter.

  3. We'll also need a JavaScript source file that we can watch for changes and perform a quality analysis on. Let's create a file called sample.js in our project root and provide it with the following contents:

    var sample = 'Sample';
    console.log(sample);
  4. Now, we can set up the example jshint task, which we'll run using the watch task by adding the following to our configuration:

    jshint: {
      sample: {
        src: ['sample.js']
      }
    }
  5. With the plugin installed and the sample task configured, we can now configure a target on the watch task, which will run the jshint task every time the sample file called sample.js changes. This is done by adding the following to our configuration:

    watch: {
      sample: {
        files: ['sample.js'],
        tasks: ['jshint']
      }
    }
  6. Finally, we can start the task using the grunt watch command, which should produce the following output to confirm that it's running:

    Running "watch" task
    Waiting...
    
  7. To test our setup, we can now make some changes to the sample.js file and save them. This should produce output informing us of the file event similar to the following:

    Running "watch" task
    Waiting...
    >> File "sample.js" changed.
    Running "jshint:sample" (jshint) task
    >> 1 file lint free.
    
    Done, without errors.
    Completed in 1.0s at Wed Jan 1 2014 00:00:00 GMT - Waiting...
    

There's more...

The watch task plugin provides many more useful configuration options that allow us to watch more than one file, run a series of tasks, prevent process spawning for task runs, enable the interruption of task runs, specify the waiting period before rerunning tasks, run tasks only on specific file events, allow tasks to kill the watcher process, and run tasks once when the watcher starts up.

Watching more than one file

In case we'd like to watch more than one file, the pattern-matching capabilities of the standard Grunt files configuration can be used. The following configuration example will observe all the files in the project root or any of its sub directories with the txt extension:

watch: {
  sample: {
    files: ['**/*.txt'],
    tasks: ['sample']
  }
}

Tip

You can find out more about the file's configuration and the globbing patterns it supports at the following URL:

http://gruntjs.com/configuring-tasks#files

Running a series of tasks

In case we'd like to run more than one task each time a file event is observed, we can just add the tasks to the array passed to the tasks configuration:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample', 'another', 'finally']
  }
}

Tip

The tasks specified in using the tasks configuration are run one at a time, in the order they are placed inside the array.

Preventing process spawning for task runs

The default behavior of the watch task is to start each of the triggered tasks in their own child process. This prevents failing triggered tasks from causing the watch task itself to fail. As a side effect, it also clones the context of the watcher process for each task. This behavior can however be disabled by setting the spawn option to false, which triggers tasks a little faster and allows them to share a context between them. The following demonstrates the configuration for this:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample'],
    options: {
      spawn: false
    }
  }
}

Enabling the interruption of task runs

The default behavior for the watcher is to wait for the completion of the tasks triggered by the previous change, before waiting for changes again. By setting the interrupt option to true, the watcher will stop running tasks when a change is detected and start rerunning them. The following demonstrates the configuration for this:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample'],
    options: {
      interrupt: true
    }
  }
}

Specifying the waiting period before rerunning tasks

The default period the watcher will wait before checking for file changes after a previous task run is 500ms. This amount of time can be changed by setting the debounceDelay option to the number of milliseconds you'd like for it to wait. The following demonstrates the configuration for this:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample'],
    options: {
      debounceDelay: 1000
    }
  }
}

Run tasks only on specific file events

In addition to being changed, files can also be added and deleted. The default behavior of the watcher is to observe all these events, but if you'd like it to run tasks only on specific events, the event option can be set to either changed, added, deleted, or all.

The following example will only start the sample task if a file named sample.txt is added or deleted to the same path as the configuration file:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample'],
    options: {
      event: ['added', 'deleted']
    }
  }
}

Allowing tasks to kill the watcher process

Warnings and failures that are raised by the tasks started by the watch task will, by default, not interrupt its execution. Setting the forever option to false will disable this behavior and allow child tasks to stop the watcher process on warnings and failures. The following demonstrates the configuration for this:

watch: {
  options: {
    forever: false
  },
  sample: {
    files: ['sample.txt'],
    tasks: ['sample']
  }
}

Tip

Note that the forever option is a task-level option only and cannot be specified for individual targets.

Running tasks once at startup of the watcher

In the case that you'd like to run the tasks specified in the tasks option once the watcher starts up, and not only once file events are observed, you can set the atBegin option to true. The following demonstrates the configuration for this:

watch: {
  sample: {
    files: ['sample.txt'],
    tasks: ['sample'],
    options: {
      atBegin: true
    }
  }
}