I`m new to Grunt and I saw a few tutorials about watch plugin. The example:
watch:{
sass:{
files: 'sass/*.scss',
tasks: ['sass','cssmin']
}
}
My question is why do I need to watch about another plungin like "sass" instead of watching the actual file(s) 'sass/*.scss'?
I don`t understand, it is not logical to watch a plugin/task, rather than a file.
Why I can`t call like this:
watch:{
files: 'sass/*.scss',
tasks: ['sass','cssmin']
}
?
And what if I want to also watch about my js file? Do I need to put it also in the files of the sass tasks? It does not make sense to have js files into sass task...
You're by no means watching a plugin. Suppose you have another plugin less, which you want to work on a different set of files. How will you do it?
watch {
sass: ...
less: ...
uglify: ...
}
Even if you put js files with sass (ignoring that it is horrible practice), when grunt calls sass on that file, nothing will happen.
As an example
module.exports = function (grunt) {
grunt.initConfig({
jshint: {
// ...
},
uglify: {
// ...
},
sass: {
// ...
},
foo: {
// ...
},
watch: {
javascript: {
files: 'javascripts/*/**.js',
tasks: ['jshint', 'uglify']
},
sass: {
files: 'sass/*/**.scss',
tasks: ['sass', 'foo']
}
}
});
// ...
};
There are different watchers for js, like uglify.
It's not that you're "watching" that plugin, it's that you're watching a set of files and running tasks when the files changes. the tasks specification is where you specify what tasks you need. So in this case you would run the sass and cssmin tasks.
The watch plugin watches files matching the pattern specified by files section. Whenever any of the matching files are changed, the tasks mentioned in tasks is executed.
For example, let us consider the watch task in your question
watch:{
sass:{
files: 'sass/*.scss',
tasks: ['sass','cssmin']
}
}
Here, sass is just a name given to the operation. It can be anything; but since the operation compiles Saas files, the operation is named saas.
Whenever any scss file in sass directory is changed, the operation saas is triggered, executing the saas and cssmin tasks, which should be defined earlier.
References:
Getting Started - Grunt: The JavaScript Task Runner
Related
I have a Grunt files as follows,
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
'uglify': {
options: {
preserveComments: 'some',
},
my_target: {
files: {
'site/assets/js/js_code.js': [
/* Libs */
'/js/libs/jquery_2.2.4.min.js',
'/js/libs/underscore_1.8.3.min.js',
'/js/libs/backbone_1.3.3.min.js',
/* Plugins */
'/js/plugins/dropzone.min.js',
'/js/plugins/jquery.magnific-popup.min.js',
'/js/plugins/jquery.validate.min.js',
/* Build JS Functions */
'/js/functions.js',
'/js/builder.js',
]
}
}
},
'sass': {
dist: {
options: {
style: 'expanded',
compass: true,
},
files: {
'assets/css/styles.css': '/scss/styles.scss',
} //End of Files
} //End of Dist.
}, //End of SASS
watch: {
'JS': {
files: ['/js/*.js'],
tasks: ['uglify'],
options: { spawn: false },
},
'Scss': {
files: ['/scss/*.scss'],
tasks: ['sass'],
options: { spawn: false },
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
};
What I can not work out, and I have done lots of research but cant seems to find an answer, is how to set up uglify to have more than one task.
I know I can set up more than one file target but I dont want my watch to running these. So I want to be setup a 'libs.js', 'plugins.js' and something like 'my_code.js'. But I don't want the libs and plugins to be run each time my code is edited/updated. But what to be able to set it up in a way so that I can run something like, grunt uglify-libs.
Is that doable?
Many thanks
UPDATE
As per comments below, I try to explain in more detail.
Right now, I run grunt watch Which returns one output file.
I want to change this to have three output files, one for the libs files, one for the plugins and the other would be the code I write.
So when I run Grunt watch, that would only watch the files in my code but not any of the libs or plugins files.
Then I want to be able to run, Grunt uglify-libs, this would then make the libs file.
Same goes for the plugins, but something like, Grunt uglify-plugs.
So basically I want three uplify tasks but only one of them is run within the watch function.
Hope that help explain more.
Many thanks.
If i understood you right, you want to use one grunt-command to start multiple tasks. You can do this by creating a "parent" tasks, who calls multiple sub-tasks like this:
grunt.registerTask('uglify-libs', ['sass', 'uglify']);
I looked at the official Grunt documentation for creating tasks here
http://gruntjs.com/creating-tasks
I have two tasks that I want to do, but the second one cannot run until after the first one completes. That's because the second task takes the output from the first task and uses it to create new output.
To break it down
My project involves Bootstrap, so it has a lot of unused code. My first objective is to remove the unused code with uncss. I would then take the output from this new css file and minify it with cssmin.
Here was the exact example from gruntjs
grunt.registerTask('foo', 'My "foo" task.', function() {
// Enqueue "bar" and "baz" tasks, to run after "foo" finishes, in-order.
grunt.task.run('bar', 'baz');
// Or:
grunt.task.run(['bar', 'baz']);
});
I tried to apply this to my code here
grunt.registerTask('default', 'uncss', function() {
grunt.task.run('cssmin');
});
This means that when grunt is entered, the default is to run the uncss task first, wait for it to complete, then run the cssmin task. However I got this output
Running "default" task
Running "cssmin:css" (cssmin) task
1 file created. 3.38kb -> 2.27kb
Done, without errors
Here is my initConfig
uncss: {
dist: {
files: {
'directory/assets/stylesheets/tidy.css': ['directory/*.html', 'directory/views/*.html']
}
}
},
cssmin: {
css: {
files: {
'directory/assets/stylesheets/styles.min.css': ['directory/assets/stylesheets/styles.css']
}
}
}
In other words, I have two stylesheets in my folder. One contains the custom styles I created, and another contains Bootstrap minified. By running uncss, I will get a new css file named tidy.css.
The cssmin task is supposed to look for this tidy.css file and minify it resulting in a new styles.min.css file.
I can get this to work, but I have to manually run one task and then run another one. How can I automate this to have them run in sequence
first, best practice is to use npm package to load all tasks automatically:
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
here are two grunt tasks:
one: {
wake up...
},
two: {
dress up...
},
and here is how you run one after the other
grunt.registerTask('oneThenOther', [
'one',
'two'
]);
You're close. When registering your alias task pass an array of tasks in the sequence you desire instead of a single task.
grunt.registerTask('default', ['uncss', 'cssmin']);
Alternatively, the sequence can be specified via the CLI:
> grunt uncss cssmin
It turns out part of the problem was I was specifying the wrong file under cssmin.
Changing my cssmin config to
cssmin: {
css: {
files: {
'directory/assets/stylesheets/styles.min.css': ['directory/assets/stylesheets/tidy.css']
}
}
}
and then registering the tasks in an array solved it
grunt.registerTask('default', ['uncss', 'cssmin']);
Note that the tasks must be specified in that order.
I am using grunt/watch for the first time:
My Gruntfile.js is configured as follows:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
all: {
options: {
livereload: true
},
files: ['**/*.gsp,**/.css']
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-watch');
};
The problem i am facing is when i run the watch task to check only css or gsp file type like files: ['**/.css'] or files: ['**/.gsp'] it works fine and detects changes in the files but when i try to watch them both files: ['**/*.gsp,**/.css'], it doesn't detect any changes (keeps showing waiting on the command line). How to make it work so that it detects the changes in both the file types .?
At the end of the day i want to do this ( image) :
Any insight will be helpful..Thanks in advance!
The best syntax will be:
files: ['./{,*/}*.{gsp,css}']
As you can see grunt accepts arrays of extensions
Ok, bassed in your edit, this should be the best solution
files: ['./grails-app/{,*/}*.gsp',
'./web-app/{,*/}*.{css,gsp}']
It is probably easier and more readable to express the functionality you want in the following way:
files: ['**/*.gsp', '**/*.css']
And for the file hierarchy you just posted:
files: [ 'grails-app/**/*.gsp', 'web-app/**/*.css', 'web-app/**/*.js' ]
I've the following Grunfile.js File:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/style.css': 'css/style.scss'
}
}
},
watch: {
stylesheets: {
files: ['css/*.scss'],
tasks: ['newer:sass']
}
}
});
// Load the plugin that compiles sass
grunt.loadNpmTasks('grunt-contrib-sass');
// watch for, and run grunt if files change
grunt.loadNpmTasks('grunt-contrib-watch');
// Plugin for Grunt tasks to run with newer files only.
grunt.loadNpmTasks('grunt-newer');
// Grunt Tasks:
grunt.registerTask('default', ['newer:sass']);
};
After running grunt watch and saving my scss File, the console output is the following:
Running "watch" task
Waiting...
>> File "css\style.scss" changed.
Running "newer:sass" (newer) task
Running "newer:sass:dist" (newer) task
Running "sass:dist" (sass) task
File css/build/style.css created.
Running "newer-postrun:sass:dist:1:D:\xampp\htdocs\grunt-test\node_modules\grunt-newer\.cache" (newer-postrun) task
Done, without errors.
The problem is, the .scss file is compiled every time. Even if there was no change.
I don't understand why grunt is running 3 tasks (newer:sass, newer:sass:dist, sass:dist), instead of only running the task defined under watch (newer:sass).
Hope someone has an idea to fix this. :)
I'm not positive this is the problem, but try specifying that you don't want to run all of sass, just sass:dist. So try: grunt.registerTask('default', ['newer:sass:dist']);
I want to run a local sync daemon.
It should watch src directory and copy any changed file to dst directory. There are many subdirectories in src, so the relative paths should be preserved. All necessary subdirectories in dst are already created.
I want to filter for *.js files only.
I've found a grunt-sync tool. The documentation is so short that I even don't know if it fits me. Here's my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
sync: {
main: {
files: [{
cwd: src,
src: ['**/*.js'],
dest: dst
}]
}
}
});
grunt.loadNpmTasks('grunt-sync');
grunt.registerTask('default', 'sync');
};
When I run grunt, I see no watch task. Grunt freezes for several seconds, then copies all files and exits. And I want a watch-sync daemon.
I created a tool called duplicate which will do what you want (though a year later), it copies all matching files when start, and keep watching if there would be any changes.
It's not written as a Gulp or Grunt plugin because it doesn't need to be, but of course you may easily run it in a Gulp or Grunt task.
Check out https://github.com/vilic/duplicate
Probably a bit late but.. I had the same question. What I´ve done is to combine both tools.. grunt-sync and grunt-contrib-watch..
module.exports = function (grunt) {
grunt.initConfig({
sync: {
main: {
files: [{
cwd: src,
src: ['**/*.js'],
dest: dst
}]
}
},
watch: {
jsxfiles: {
files: ['**/*.js'],
tasks: ['sync:main'],
} //this means that when any of the pattern files changes, the sync task will be run...
}
});
grunt.loadNpmTasks('grunt-sync');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', 'watch'); //run the watch task isntead of just the sync once..
};
I hope this is helpful
KR Jon