Configure Grunt tasks to run with newer files only.
Synopsis: The 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.
This plugin requires Grunt ~0.4.1
If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a gruntfile.js
as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
npm install grunt-newer --save-dev
Once the plugin has been installed, it may be enabled inside your gruntfile.js
with this line:
grunt.loadNpmTasks('grunt-newer');
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 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.
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 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.
grunt.initConfig({
jshint: {
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.
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.
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.
- 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:
grunt.initConfig({
newer: {
options: {
cache: 'path/to/custom/cache/directory'
}
}
});
- 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 asrc
file that appears to be "older" (not modified since the time below). - time -
Date
The comparison time. For tasks withdest
files, this is the modification time of thedest
file. For tasks withoutdest
files, this is the last successful run time of the same task.
- task -
- include -
function(boolean)
A callback that determines whether thissrc
file should be included. Call withtrue
to include orfalse
to exclude the file.
Example use of the override
option:
grunt.initConfig({
newer: {
options: {
override: function(detail, include) {
if (detail.task === 'less') {
checkForModifiedImports(detail.path, detail.time, include);
} else {
include(false);
}
}
}
}
});
- type:
number
(milliseconds) - default:
0
The newer
tasks compares the file modification times of the source and destination files with millisecond precision.
On some file systems this causes destination files to always be considered older because of imprecision in the registration of modification times.
If your tasks are always run even though the source files are not modified use the tolerance
option to compensate for this imprecision.
In most cases setting the option to 1000
milliseconds should be enough. If the file system is very imprecise use a higher value.
Example use of the tolerance
option:
grunt.initConfig({
newer: {
options: {
tolerance: 1000
}
}
});
Please submit an issue if you encounter any trouble. Contributions or suggestions for improvements welcome!
The newer
task relies on Grunt's convention for specifying src
/dest
mappings. So it should be expected to work with two types of tasks:
-
Tasks that specify both
src
anddest
files. In this case, the task prefixed bynewer
will be configured to run withsrc
files that are newer than the correspondingdest
file (based on themtime
of files). -
Tasks that specify only
src
files. In this case, the task prefixed bynewer
will be configured to run withsrc
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
- Though this task specifiessrc
anddest
files, thedest
file is not generated based onsrc
files (instead it is a directory).