# grunt-newer
Configure [Grunt](http://gruntjs.com/) tasks to run with newer files only.
**Synopsis:** The [`newer`](#newer) task will configure another task to run with `src` files that are *a)* newer than the `dest` files or *b)* newer than the last successful run (if there are no `dest` files). See below for examples and more detail.
## Getting Started
This plugin requires Grunt `~0.4.1`
If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [`gruntfile.js`](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
```shell
npm install grunt-newer --save-dev
```
Once the plugin has been installed, it may be enabled inside your `gruntfile.js` with this line:
```js
grunt.loadNpmTasks('grunt-newer');
```
## The `newer` task
The `newer` task doesn't require any special configuration. To use it, just add `newer` as the first argument when running other tasks.
For example, if you want to use [Uglify](https://npmjs.org/package/grunt-contrib-uglify) to minify your source files only when one or more of them is newer than the previously minified destination file, configure the `uglify` task as you would otherwise, and then register a task with `newer` at the front.
```js
grunt.initConfig({
uglify: {
all: {
files: {
'dest/app.min.js': ['src/**/*.js']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('minify', ['newer:uglify:all']);
```
With the above configuration the `minify` task will only run `uglify` if one or more of the `src/**/*.js` files is newer than the `dest/app.min.js` file.
The above example shows how the `newer` task works with other tasks that specify both `src` and `dest` files. In this case, the modification time of `src` files are compared to modification times of corresponding `dest` files to determine which `src` files to include.
The `newer` task can also be used with tasks that don't generate any `dest` files. In this case, `newer` will only use files that are newer than the last successful run of the same task.
For example, if you want to run [JSHint](https://npmjs.org/package/grunt-contrib-jshint) on only those files that have been modified since the last successful run, configure the `jshint` task as you would otherwise, and then register a task with `newer` at the front.
```js
grunt.initConfig({
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: {
src: 'src/**/*.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('lint', ['newer:jshint:all']);
```
With the above configuration, running `grunt lint` will configure your `jshint:all` task to use only files in the `jshint.all.src` config that have been modified since the last successful run of the same task. The first time the `jshint:newer:all` task runs, all source files will be used. After that, only the files you modify will be run through the linter.
Another example is to use the `newer` task in conjunction with `watch`. For example, you might want to set up a watch to run a linter on all your `.js` files whenever one changes. With the `newer` task, instead of re-running the linter on all files, you only need to run it on the files that changed.
```js
var srcFiles = 'src/**/*.js';
grunt.initConfig({
jshint: {
all: {
src: srcFiles
}
},
watch: {
all: {
files: srcFiles,
tasks: ['newer:jshint:all']
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-newer');
```
With the above configuration, running `grunt jshint watch` will first lint all your files with `jshint` and then set up a watch. Whenever one of your source files changes, the `jshint` task will be run on just the modified file.
*Note:* If your task is configured with `dest` files, `newer` will run your task with only those files that are newer than the corresponding `dest` files.
## Options for the `newer` task
In most cases, you shouldn't need to add any special configuration for the `newer` task. Just `grunt.loadNpmTasks('grunt-newer')` and you can use `newer` as a prefix to your other tasks. The options below are available for advanced usage.
#### options.cache
* type: `string`
* default: `node_modules/grunt-newer/.cache`
To keep track of timestamps for successful runs, the `newer` task writes to a cache directory. The default is to use a `.cache` directory within the `grunt-newer` installation directory. If you need timestamp info to be written to a different location, configure the task with a `cache` option.
Example use of the `cache` option:
```js
grunt.initConfig({
newer: {
options: {
cache: 'path/to/custom/cache/directory'
}
}
});
```
#### options.override
* type: `function(Object, function(boolean))`
* default: `null`
The `newer` task determines which files to include for a specific task based on file modification time. There are occassions where you may want to include a file even if it has not been modified. For example, if a LESS file imports some other files, you will want to include it if any of the imports have been modified. To support this, you can provide an `override` function that takes two arguments:
* **details** - `Object`
* **task** - `string` The currently running task name.
* **target** - `string` The currently running target name.
* **path** - `string` The path to a `src` file that appears to be "older" (not modified since the time below).
* **time** - `Date` The comparison time. For tasks with `dest` files, this is the modification time of the `dest` file. For tasks without `dest` files, this is the last successful run time of the same task.
* **include** - `function(boolean)` A callback that determines whether this `src` file should be included. Call with `true` to include or `false` to exclude the file.
Example use of the `override` option:
```js
grunt.initConfig({
newer: {
options: {
override: function(detail, include) {
if (detail.task === 'less') {
checkForModifiedImports(detail.path, detail.time, include);
} else {
include(false);
}
}
}
}
});
```
## That's it
Please [submit an issue](https://github.com/tschaub/grunt-newer/issues) if you encounter any trouble. Contributions or suggestions for improvements welcome!
[](https://travis-ci.org/tschaub/grunt-newer)
## Known limitations
The `newer` task relies on Grunt's convention for specifying [`src`/`dest` mappings](http://gruntjs.com/configuring-tasks#files). So it should be expected to work with two types of tasks:
1) Tasks that specify both `src` and `dest` files. In this case, the task prefixed by `newer` will be configured to run with `src` files that are newer than the corresponding `dest` file (based on the `mtime` of files).
2) Tasks that specify only `src` files. In this case, the task prefixed by `newer` will be configured to run with `src` files that are newer than the previous successful run of the same task.
The `newer` task will *not* work as a prefix for the following tasks:
* [`grunt-rsync`](http://npmjs.org/package/grunt-rsync) - Though this task specifies `src` and `dest` files, the `dest` file is not generated based on `src` files (instead it is a directory).
* [`grunt-spritesmith`](https://npmjs.org/package/grunt-spritesmith) - This task uses multiple `src` images to produce `destImg` and `destCSS` files. Instead use the [`grunt-spritely`](https://npmjs.org/package/grunt-spritely) task configured with `src` and `dest` files.