Grunt watcher for javascript concat - javascript

I'm trying to concatenate all javascript files inside my controllers directory into one file, located one level higher. This is the code I'm using:
concat: {
dist: {
files: {
'<%= yeoman.app %>/scripts/all.js': [
'<%= yeoman.app %>/scripts/controllers/{,*/}*.js',
'<%= yeoman.app %>/scripts/controllers/{,*/}*.js'
]
}
}
}
It works fine, but I'm forced to manually type grunt concat in console every time I change my javascript files. So I'm trying to get this done with a watcher but can't get it to work. This is my watcher code:
concat: {
files: ['<%= yeoman.dist %>/scripts/controllers/*.js'],
tasks: ['concat']
},

You will need to type "grunt watch" when you want to have watch monitor the files. You'll need to add the watch task in your "Gruntfile.js" like so:
watch: {
concat: {
files: ['<%= yeoman.dist %>/**/*.js'],
tasks: "concat"
}
}
Your concat task still needs to be there as you currently have.
Make sure you install grunt-contrib-watch as well..
npm install grunt-contrib-watch --save-dev
Check out the github page for grunt-contrib-watch for more info on these: https://github.com/gruntjs/grunt-contrib-watch

Related

Grunt watch pattern.indexOf is not a function

I'm trying to use Grunt's grunt-contrib-watch plugin to watch some files and then run the tasks, just what it was made for, this is my Gruntfile.js
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
dist: {
files: {
'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss',
/*'bower_components/foundation-sites/dist/foundation.min.css': 'bower_components/foundation-sites/scss/foundation.scss'*/
}
}
},
uglify: {
dist: {
files: {
'static/javascript/main.min.js': 'static/javascript/main.js'
}
}
},
watch: {
files: [
'<%= sass.dist.files %>',
'<%= uglify.dist.files %>'
],
tasks: [
'sass',
'uglify'
]
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['watch']);
};
When I run it, it runs over and over and over again, and when I stop it, I see I have this message:
Running "watch" task
Waiting...
Warning: pattern.indexOf is not a function
I really don't know what's the problem. Does anybody know what happens here?
UPDATE:
Apparently, the problem is because of the way I call the files, because I changed it to: 'static/stylesheets/sass/*.scss' and it worked well, but I would like to know why the other way doesn't work, because I think is a more useful way to do it.
grunt-contrib-watch expects either a single pattern string or an array of pattern strings as the value of its files config. However, the templates you are using in your config evaluate to objects. Your watch.files value evaluates to the following:
files: [
{ 'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss' },
{ 'static/javascript/main.min.js': 'static/javascript/main.js' }
]
When the pattern matching tries to run it fails because there is no indexOf method on an Object. Due to the fact that grunt-contrib-watch runs forever, there is an infinite loop of the trying and failing to build the list of watched files.
You would normally configure your watch files with something like the following:
files: [
'static/**/*.scss',
'static/**/*.js'
]
But the above will cause issues in your case because your minified JS file is in the same folder as your source JS file. You could probably get around this by adding '!static/**/*.min.js' to your files array, but a better solution would be to put all of your compiled files into a separate folder.
Extract the values from the object:
watch: {
files: [
'<%= sass.dist.files.values() %>',
'<%= uglify.dist.files.values() %>'
],

Source map to files outside public directory

I have a file structure like this:
/server/
- package.json
- node_modules/
- Gruntfile.js
/public/
- index.html
- assets/
When in /server I run npm install, which downloads things like Angular into /server/node_modules.
I then run the Gruntfile.js which looks like this:
require('load-grunt-tasks')(grunt);
grunt.initConfig({
//concat js
concat: {
options: {
separator: ';',
sourceMap: true
},
lib: {
src: [
'./node_modules/angular/angular.js',
'./node_modules/angular-route/angular-route.js',
'./node_modules/angular-animate/angular-animate.js'
],
dest: '../public/assets/build/lib/lib.min.js'
}
},
//minify js
uglify: {
options: {
mange: true,
compress: true,
sourceMap: true
},
lib: {
src: '<%= concat.lib.dest %>',
dest: '<%= concat.lib.dest %>'
}
}
});
grunt.registerTask('build', ['concat', 'uglify']);
The grunt file works as expected to concat and minify the Angular modules with a source map. The problem is that the domain name points to the public directory, but the source map wants to point to the Angular source code in the server directory, which I don't think will work.
How do I get around this problem? Do I have to have the node_modules in the root of the public directory? I'd rather not have any precompiled code in the public directory if possible, the reason being that when I put the site live, I can simply FTP the public directory and ignore the server, reducing unnecessary bulk.

Grunt no longer livereloads

I'm new to web development and I'm trying to build a small webapp. I used yoeman to set everything up and it did pretty well, angular installed perfectly and I installed angular-animate and jquery-ui after with bower. Autoreloading the webpage happend automagically, I really liked it.
After a while it stoped livereloading my changes. I don't know why. I'm not sure what I did.
This is what my gruntfile watch section looks like:
// Watches files for changes and runs tasks based on the changed files
watch: {
js: {
files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
tasks: ['newer:jshint:all'],
options: {
livereload: true
}
},
jsTest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['newer:jshint:test', 'karma']
},
styles: {
files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
tasks: ['newer:copy:styles', 'autoprefixer']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
}
It looks ok right? No errors showing up when running:
grunt serve
I had the same problem where LiveReload would stop working after a while.
What worked for me was reinstalling the LiveReload Chrome Extension, so if you didn't make any changes to the Gruntfile you can try that.

Compile, Concatenate and Minify Sass files with Grunt

I'm building a sizable JS application using angularjs, and I'm using Grunt to process everything into a compact distribution. I can't figure out what to use to compile, concat and minify my .scss files into one single css file.
My project is organized by modules, so the .scss files are scattered, rather than grouped in a single directory.
I've looked at grunt-contrib-sass and grunt-contrib-compass, but they both seem to require you to individually specify files to compile. I'm looking for a solution that won't have to change when I add source files.
What Grunt plugin can I use to compile, concat and minify my sass files into a single css file?
I'm currently using concat and recess to concat and minify my plain css files:
concat: {
css: {
src: ['<%= src.css %>'],
dest: '<%= distdir %>/<%= pkg.name %>.css'
},
},
recess: {
min: {
files: {
'<%= distdir %>/<%= pkg.name %>.css': ['<%= distdir %>/<%= pkg.name %>.css']
},
options: {
compress: true
}
}
}
I think a documentation about patterns can help you.
http://gruntjs.com/configuring-tasks#globbing-patterns
sass: { // Task
dist: { // Target
options: { // Target options
style: 'expanded'
},
src: 'foo/{a,b}*.sass', // you can use some kind of regular expression
dest: 'foo/css/
}
}

How do I tell Grunt to NOT minify or concatenate js files in a build task?

I've just scaffolded an Angular app using Yeoman. I've noticed that the build task does several things by default, including minifying and concatenating js files.
I'd like to have a simpler build task that didn't do any minifying or concatenation, and, instead, only did the following two things:
compile my .scss into .css
copy a working app into my distribution directory
Can anyone help me write a grunt task that will do (only) these two things?
Many thanks.
Ok, I've edited the default grunt file so that it does what I want.
My solution involved writing tasks called copy:devDist and compass:devDist, and then combining them into a devDist task.
//
// copy:devDist --> copies everything into the dist folder, except styles/
//
copy: {
[...]
devDist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'**','!styles/**' // everything but styles/
]
}]
}
},
//
// compass:devDist --> compile the sass; put result in dist/styles/
//
compass: {
[...]
devDist: {
options: {
cssDir: '<%= yeoman.dist %>/styles'
}
}
},
//
// register a 'devDist' task that calls the two tasks above
//
grunt.registerTask('devDist', [
'clean:dist',
'copy:devDist',
'compass:devDist'
]);
Now running grunt devDist compiles my css and puts a fully functional app into my dist folder. Excellent. :)

Categories