Referencing a module / script when using npm and grunt - javascript

I'm looking into npm, grunt and bower, and I've made my first task which looks like this.
module.exports = function(grunt){
grunt.initConfig({
concat: {
options: {
separator: ';',
},
dist: {
src: ['node_modules/jquery/dist/jquery.js', 'node_modules/handlebars/dist/handlebars.js'],
dest: 'dist/scripts.js',
},
},
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
I was wondering if there's an easier/better way of adding the scripts. So that instead of typing the whole path you could just do src: [jquery, 'handlebars'],
and if bower is of any use regarding this?
Thank you.

Related

Error: ENOENT in Grunt uglify task

I have the following gruntfile.js. Using grunt-contrib-concat and grunt-contrib-uglify together.
This is an extention of a developement asked #Dynamic Mapping and Concat with Grunt Uglify
I use banner in the uglify task to reference a file created in the concat task.
module.exports = function(grunt){
// Configure task(s)
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// setup concats
concat: {
options: {
separator: ';\n',
},
dev: {
files: [{
src: [
'sports.js',
'salon.js',
'offRoad.js',
],
dest: 'src/js/concat/car-dev.js'
}],
},
},
// setup uglify task
// this will produce a car js file (which includes car-dev.js) for every car js file located within scr/js/cars/
uglify: {
// dev - use in development mode, global overrides section
dev: {
options: {
// include concat dev.js
banner: grunt.file.read('src/js/concat/car-dev.js'),
beautify: true,
mangle: false,
compress: false,
preserveComments: 'all'
},
files: [{
expand: true,
cwd: 'src/js/cars/',
src: '*.js',
dest: 'javascript/dev',
ext: '.dev.js',
extDot: 'first'
}],
},
},
});
// Load the plugins
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
// Register task(s)
grunt.registerTask('default',
'concat:dev'
'uglify:dev'
]);
};
My issue is that if src/js/concat/car-dev.js doesn't exist, I get the following error:
Error: Unable to read "src/js/concat/car-dev.js" file <Error code: ENOENT).
If I create an empty file #src/js/concat/car-dev.js the grunt command works fine.
However this is not always possible. I want uglify to reference the car-dev.js file even if it doesn't exist. What I'm looking for is someway to reference the grunt->concat->dev->files->dest file.
I've tried adding the following
banner: grunt.file.read(grunt.concat.dev.files.dest),
and
banner: grunt.concat.dev.files.dest
but neither work. Is this possible?
This is not a task dependency issue - the error gets thrown before any tasks are run because banner: src/js/concat/car-dev.js does not exist.
Any help - much appreciated.

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() %>'
],

Grunt - Concat multiple JS files and watch for changes

Still a bit of a newbie with Grunt, so please bear that in mind with your answers. I am trying to setup a task in Grunt that will concat any JS files within a directory called "custom", into a single file called custom-concat.js, however after running grunt watch (which runs fine without error), nothing is happening when I try and make changes to any of the files within my "custom" directory (i.e. console just sits at "waiting...." even after I make changes to any JS files within "custom" directory). Clearly there is something wrong with my concat task, but I can't seem to see what the problem is. Can anyone see where the problem lies? Full gruntfile below:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
//pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';',
},
dist: {
src: ['scripts/custom/**/*.js'],
dest: 'scripts/custom-concat.js',
},
},
uglify: {
build: {
src: 'scripts/custom-concat.js',
dest: 'scripts/custom.min.js'
}
},
less: {
options: {
paths: ["css"]
},
files: {
"styles.css": "less/styles.less"
}
},
watch: {
scripts: {
files: 'scripts/**/*.js',
task: ['concat', 'uglify:build']
},
styles: {
files: 'css/less/**.less',
task: 'less'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['concat', 'uglify']);
};
As far as I see, there are three small issues with your watch task:
The correct attribute for watch is taskS not task
If you want to run the tasks of watch, directly at the beginning, use options { atBegin: true }
Your watch task monitors the script folder. However, this folder will also contain your concated and uglified files. So this task will run into an infinite loop. You should probably only watch the scripts/custom folder
So your watch task should probably look something like this:
watch: {
scripts: {
files: 'scripts/custom/**/*.js',
tasks: ['concat', 'uglify:build'],
options: {
atBegin: true
}
},
styles: ...
}
Github grunt-contrib-watch

How to ignore files grunt uglify

Background
I've just started using grunt as of about 30mins ago. So bear with me.
But I have a rather simple script going that will look at my js and then compress it all into one file for me.
Code
"use strict";
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
beautify: true,
report: 'gzip'
},
build: {
src: ['docroot/js/*.js', 'docroot/components/pages/*.js', 'docroot/components/plugins/*.js'],
dest: 'docroot/js/main.min.js'
}
},
watch: {
options: {
dateFormat: function(time) {
grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
grunt.log.writeln('Waiting for more changes...');
}
},
js: {
files: '<%= uglify.build.src %>',
tasks: ['uglify']
}
}
});
grunt.registerTask('default', 'watch');
}
Question
My main.min.js is getting included in the compile each time. Meaning my min.js is getting 2x, 4x, 8x, 16x etc etc. Is best way around this is to add an exception and ignore main.min.js?
To the end of the src array, add
'!docroot/js/main.min.js'
This will exclude it. The ! turns it into an exclude.
http://gruntjs.com/api/grunt.file#grunt.file.expand
Paths matching patterns that begin with ! will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.
This is not specific to grunt uglify, but any task that uses grunt convention for specifying files will work this way.
As a general advice though I would suggest putting built files somewhere else than your source files. Like in a root dist folder.

grunt: how to generate jshint output as HTML

I'm trying to run jshint using grunt. This works, but now I would like the output to be HTML. Here is my grunt file
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
jshint: {
all: ['Gruntfile.js', 'src/*.js']
, options: {
//reporter: 'jslint'
reporter:'checkstyle'
, reporterOutput: 'jshint.html'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
};
Running this grunt taks, the output is in XML. Any suggestion how to turn this into something that outputs HTML ?
Thanks a lot
You would need to write a custom reporter. Check the jshint docs on writing custom reporters: http://jshint.com/docs/reporters/ Then you can specify the path to the reporter with:
options: {
reporter: '/path/to/custom/html/reporter',
reporterOutput: 'jshint.html'
}
You can use jshint reporter from nodejs
This generates output in HTML
https://www.npmjs.com/package/jshint-html-reporter
Include this in your GruntFile.js
grunt.initConfig({
jshint: {
options: {
reporter: require('jshint-html-reporter'),
reporterOutput: 'jshint-report.html'
},
target: ['file.js']
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['jshint']);

Categories