i'm using grunt tasks to watch and concatenate some js files.
my first configuration worked fine:
grunt.initConfig({
watch: {
js: {
files: ['web/**/*.js'],
tasks: ['concat:JS']
}
},
concat: {
JS: {
files: {
"index.js": [
"test-1.js",
"test-2.js",
],
"about_us.js": [
"test-3.js",
"test-4.js",
],
"store.js": [
"test-5.js",
"test-6.js",
]
}
}
}
});
my problem is that with this configuration whenever i change a file it concatenates everything.
i would be able to concatenate only a specific file (based on which file changed).
e.g. if i change test-1.js
i would like concatenate only the index.js
file (..so the task to run should be 'concat:JS:index.js'
)
so i tryed adding a watch event
grunt.event.on('watch', function(action, filepath, target) {
var taskName = "concat:JS"; //here i calculate dinamically the specific task name to be run
grunt.task.run(taskName);
});
but nothing happens.. any idea? thanks
Using the grunt.event.on('watch', ...)
listener is the wrong tool for this kind of requirement. Instead you should utilize multiple Targets for both the the watch
and concat
tasks as shown in the Gruntfile.js
excerpt below.
Gruntfile.js
grunt.initConfig({
watch: {
'JS-index': {
files: ['web/js/test-1.js', 'web/js/test-2.js'],
tasks: ['concat:JS-index']
},
'JS-about-us': {
files: ['web/js/test-3.js', 'web/js/test-4.js'],
tasks: ['concat:JS-about-us']
},
'JS-store': {
files: ['web/js/test-5.js', 'web/js/test-6.js'],
tasks: ['concat:JS-store']
}
},
concat: {
'JS-index': {
files: {
'dist/js/index.js': [
"web/js/test-1.js",
"web/js/test-2.js",
]
}
},
'JS-about-us': {
files: {
"dist/js/about_us.js": [
"web/js/test-3.js",
"web/js/test-4.js",
]
}
},
'JS-store': {
files: {
'dist/js/store.js': [
"web/js/test-5.js",
"web/js/test-6.js",
]
}
}
}
});
Notes
Given the configuration shown above, the following will happen after running grunt watch
via your CLI:
Changing either test-1.js
or test-2.js
will concatenate both files to dist/js/index.js
.
Changing either test-3.js
or test-4.js
will concatenate both files to dist/js/about_us.js
.
Changing either test-5.js
or test-6.js
will concatenate both files to dist/js/store.js
.
Your paths will need to be configured as necessary
how do i execute a task with grunt?
Using grunt.task.run
is the correct way to programmatically run a task.
However, see this comment in the grunt-contrib-watch
github repo. Excerpts from it read:
"Don't use
grunt.event.on('watch')
to run your tasks."
and...
"The watch event is not intended for running tasks."
The following solution assumes your requirement is to concatenate some .js
files when one of them is changed/edited. In which case you need to utilize the tasks
property of the watch
task to define which task to run (I.e. 'concat:JS'
)
Gruntfile
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.initConfig({
watch: {
js: {
files: ['path/to/js/**/*.js'], // <-- 1. Glob pattern to .js files
tasks: ['concat:JS'] // <-- 2. Task to run when .js file changes.
}
},
concat: { // <-- 3. Configure your `concat` task as necessary.
JS: {
src: [
'path/to/js/foo.js',
'path/to/js/bar.js',
'path/to/js/quux.js'
],
dest: 'path/to/output/combined.js'
}
}
});
grunt.registerTask('default', ['watch']);
grunt.event.on('watch', function(action, filepath, target) {
console.log("yep, this code is being executed");
// 4. <-- Do not run task from 'on' listener event.
});
}
Notes
watch
task define the glob pattern to the source .js
files to watch for changes..js
file changes; I.e. 'concat:JS'
concat
task as necessary.grunt.task.run('concat:JS');
from the grunt.event.on('watch', ...)
listener.grunt
via your cli creates a new combined.js
file when any change is made to a .js
file stored in the path/to/js/
directory. (You'll need to configure the paths as per your requirements)grunt.event.on('watch', ...)
listener should not be used to run a task, it can be utilized to configure other tasks.