Grunt : watch multiple files (js,css and gsp) within different sub folders - javascript

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' ]

Related

How to make couple of minified files from different js files using grunt

I am new to grunt and task runners in JS, so this might seem a simple question but I have been unable to find exact working answer.
I have :
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: '\n\n'
},
dist: {
// the files to concatenate
src: ['scripts/app.js', 'scripts/constant.js'
],
// the location of the resulting JS file
dest: 'scripts/custom.js'
}
},
This task collects all my custom file together. What I want is to do similar thing for all my vendors file. Finally I should end up with two js only custom.js having my concatenated-minified code and vendor.js having concatenated-minfied libraries.
How do I write grunt configuration for this. Do I need to make two different tasks. If I write the above code twice with different input files, it seems to run the last code.
grunt-contrib-concat can be configured to utilize multiple-targets.
For further documentation on this subject refer to multi-tasks and Task Configuration and Targets in the grunt documentation.
Gruntfile.js
For your scenario you need to configure your concat task similar to this (Note: the new custom and vendor targets):
module.exports = function(grunt) {
grunt.initConfig({
concat: {
options: {
separator: '\n\n'
},
custom: {
src: ['scripts/app.js', 'scripts/constant.js'],
dest: 'scripts/output/custom.js'
},
vendor: {
// Modify the src and dest paths as required...
src: ['scripts/vendor/foo.js', 'scripts/vendor/baz.js'],
dest: 'scripts/output/vendor.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('concatenate', [
'concat:custom', // <-- Targets in a task are called using a colon separator.
'concat:vendor'
]);
};
Running concat
Using the example gist provided above you can run the concat task via the CLI by typing the following command:
$ grunt concatenate
Configuring Options
If you require different configuration options for both the custom and vendor targets you will need to move the options object inside their respective targets. As explained here.
Note: Using the example gist provided the options specified will apply to both targets.

Grunt and Uglify, running more than one task?

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']);

Grunt watch for tasks instead for files?

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

grunt: Watch and synchronize files

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

Dynamically add version number to dest output files w/ grunt

I have a package.json file with our version number, such as:
{
name: "myproject"
version: "2.0"
}
My goal is to dynamically add the version number from the package.json file into the output files. For example, in the javascript I don't want to manually update the version number, but would like something similar to this to be generated after each grunt build:
/* My Project, v2.0 */
window.myProject = {
version: "2.0"
};
Is there an easy way to do this in my Gruntfile.js configuration?
I implemented: https://github.com/erickrdch/grunt-string-replace
In my source css/js files, I use the text {{ VERSION }} which gets replaced with the version number set in the package.json file. Below is the config I added to Gruntfile.js.
'string-replace': {
version: {
files: {
// the files I did string replacement on
},
options: {
replacements: [{
pattern: /{{ VERSION }}/g,
replacement: '<%= pkg.version %>'
}]
}
}
},
pkg: grunt.file.readJSON('package.json'),
I think that what you only want to do is to put some kind of trick for unable the page to use the cache files that maybe the browser have, and by now, the only way for that cross-browser is putting something on the href urls like "app.v2_2.js" or "app.js?ver=22". So I use this grunt npm package:
https://www.npmjs.org/package/grunt-cache-breaker
By default it only adds a parameter to your javascript and in almost the cases is the thing you need for not using cache, but you can configure even if you change the name of the file in other grunt process. This only change the HTML headers to what you desire.
After you install the grunt-cache-breaker, add this to your GruntFile:
// Append a timestamp to 'app.js', 'controllers.min.js' which are both located in 'index.html'
// resulting in the index the call of : href="~/app.js?rel=1415124174159"...
cachebreaker: {
dev: {
options: {
match: ['app.js', 'styles.css']
},
files: {
src: ['dist/index.html']
}
}
},
Then where you load the modules:
grunt.loadNpmTasks('grunt-cache-breaker');
Add on the task you want to:
grunt.registerTask('deploy', [
'clean:app',
'copy:views',
'copy:imgs',
'copy:css',
'uglify:app',
'cssmin:app',
'cachebreaker:dev'
]);
And finally run the grunt action on the console/command prompt
> grunt deploy
I would suggest using the banner feature in grunt-contrib-concat
this can be done as well with the banner option of https://github.com/gruntjs/grunt-contrib-uglify - which takes also care of the minifiaction of the javascript files.
filerev provides this option now. Use process to manipulate the filename that will be otherwise suffixed with md5 hash of the file content. You can use this to insert your version to every file you want.
Ref: https://github.com/yeoman/grunt-filerev
create something like package.json in the root of your project
it should read that or you can do something like
pkg: grunt.file.readJSON('package.json'),
in that you'll have a version declaration which would obviously correspond to <%= pkg.version %> so have that string in your json output and then run grunt.config.process to do the variable replacement
do something similar for the comment header

Categories

Resources