Declare multiple files in grunt - javascript

I'm new to Grunt so maybe this is an easy question, but I'm really at a loss with this...
I'm tying to declare all my files in "package.json" and inside grunt just import them.
Something like this:
// package.json
{
"config": {
"files": {
"css": ["../assets/css/main.scss", "../assets/css/plugins.scss"]
}
},
"dependencies": {
"grunt": "~0.4.5",
"grunt-contrib-sass": "~0.8.1"
}
}
// grunt.js
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dev: {
options: { style: 'compressed', noCache: true },
files: { '../assets/min/min.css': '<%= pkg.config.files.css %>' }
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('default', ['sass:dev']);
};
I says the source files are empty. But if I declare only one file it works just fine.
While if I declare them directly inside "grunt.js" works...
// grunt.js
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dev: {
options: { style: 'compressed', noCache: true },
files: { '../assets/min/min.css': ["../assets/css/main.scss", "../assets/css/plugins.scss"] }
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('default', ['sass:dev']);
};
Can someone tell me how to make the first one work?
Thanks :)

The problem is that by sticking pkg.config.files.css into the template, it's probably stringifying it. Try just passing in the variable directly:
// Wrong
'<%= pkg.config.files.css %>'
// Right
pkg.config.files.css
This way, Grunt will just pass in the array as you're expecting it to.
EDIT:
If this doesn't work, here's an alternative way to access package.json. While the above is valid JS, it may not be valid with Grunt because if grunt.file.readJSON runs asynchronously, it will be undefined until it finishes, which would be after grunt already initialized the config object. Thus, grunt goes back and inserts the data when it's available.

Related

Grunt concats JS file multiple times

I'm working on a Node.js website and I'm using Grunt to concat and minify my CSS and JS files. However, after running the grunt command I'm getting the error message:
fullPage: Fullpage.js can only be initialized once and you are doing it multiple times!
Here's my grunt file:
/*global module */
module.exports = function (grunt) {
"use strict";
grunt.initConfig({
// read in the project settings from the package.json file into the pkg property
pkg: grunt.file.readJSON("package.json"),
// Install only the bower packages that we need
bower: {
install: {
options: {
"targetDir": "./public/lib",
"copy": true,
"cleanup": true,
"install": true
}
}
},
concat: {
css: {
src: ["public/lib/css/**/*.css", "public/css/cts.css"],
dest: "public/lib/dist/main.css"
},
js: {
src: ["public/lib/**/jquery.js", "public/lib/**/*.js", "public/js/cts.js"],
dest: "public/lib/dist/main.js"
}
},
cssmin: {
target: {
files: {
"public/lib/dist/main.min.css": "public/lib/dist/main.css"
}
}
},
uglify : {
js: {
files: {
"public/lib/dist/main.min.js": "public/lib/dist/main.js"
}
}
},
copy: {
files: {
expand: true,
flatten: true,
src: ["public/lib/fonts/**/*"],
dest: "public/lib/fonts/",
filter: "isFile"
}
}
});
// Add all plugins that your project needs here
grunt.loadNpmTasks("grunt-bower-task");
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-copy");
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-contrib-watch");
// this would be run by typing "grunt test" on the command line
// the array should contains the names of the tasks to run
grunt.registerTask("test", []);
// define the default task that can be run just by typing "grunt" on the command line
// the array should contains the names of the tasks to run
grunt.registerTask("default", [ "bower", "concat", "cssmin", "uglify", "copy"]);
grunt.registerInitTask("install", ["bower"]);
};
If anything I would have thought jQuery would be the one that's getting concatenated multiple times but it's not. Any suggestions what I might be doing wrong?
EDIT: Here's my upgraded grunt file with all 3rd party libraries listed in the concat.src.
/// <binding BeforeBuild='default' />
/*global module */
module.exports = function (grunt) {
"use strict";
grunt.initConfig({
// read in the project settings from the package.json file into the pkg property
pkg: grunt.file.readJSON("package.json"),
// Install only the bower packages that we need
bower: {
install: {
options: {
"targetDir": "./public/lib",
"copy": true,
"cleanup": true,
"install": true
}
}
},
concat: {
css: {
src: ["public/lib/css/**/*.css", "public/css/cts.css"],
dest: "public/lib/dist/main.css"
},
js: {
src: [
"public/lib/js/jquery/jquery.js",
"public/lib/js/bootstrap/bootstrap.js",
"public/lib/js/fullpage.js/jquery.fullpage.js",
"public/lib/js/jquery-easing-original/jquery.easing.js",
"public/lib/js/slimscroll/jquery.slimscroll.js",
"public/lib/js/wow/wow.js",
"public/js/cts.js"
],
dest: "public/lib/dist/main.js"
}
},
cssmin: {
target: {
files: {
"public/lib/dist/main.min.css": "public/lib/dist/main.css"
}
}
},
uglify : {
js: {
files: {
"public/lib/dist/main.min.js": "public/lib/dist/main.js"
}
}
},
copy: {
files: {
expand: true,
flatten: true,
src: ["public/lib/fonts/**/*"],
dest: "public/lib/fonts/",
filter: "isFile"
}
}
});
// Add all plugins that your project needs here
grunt.loadNpmTasks("grunt-bower-task");
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-copy");
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-contrib-watch");
// this would be run by typing "grunt test" on the command line
// the array should contains the names of the tasks to run
grunt.registerTask("test", []);
// define the default task that can be run just by typing "grunt" on the command line
// the array should contains the names of the tasks to run
grunt.registerTask("default", [ "bower", "concat", "cssmin", "uglify", "copy"]);
grunt.registerTask("combine", [ "concat", "cssmin", "uglify", "copy"]);
grunt.registerInitTask("install", ["bower"]);
};
Your issue seems to be in concate.js.src
src: ["public/lib/**/jquery.js", "public/lib/**/*.js", "public/js/cts.js"]
This will have your files added multiple times as there might some files common among the paths mentioned in src.
You should probably move all your vendor files like jquery out of the public directory and put in a different one, say vendor.
Your src should then look something like
src: ["vendor/**/*.js", "public/**/*.js"]
As you see now there are no common files among these two paths.
Also its a good practice to always have 3rd party code outside your app directory as a sibling folder and not inside it.
EDIT:
Ah! I see whats your problem. You want to have jquery first among the other vendor files.
public/lib/**/jquery.js and public/lib/**/*.js together might be causing files added twice.
Try this
src: ["public/lib/jquery/jquery.js", "public/lib/**/*.js", "!public/lib/jquery/jquery.js", public/js/cts.js"]
Put the full path of jquery first public/lib/jquery/jquery.js and then the !public/lib/jquery/jquery.js should prevent jquery being added again as part of public/lib/**/*.js
Got the above pattern from here http://gruntjs.com/configuring-tasks#globbing-patterns
If this still doesn't work, then another option is to add all paths in the src array individually. If you have a requirejs config just copy the paths from there, as jquery might not be the only dependency issue you face in future.

Why is Grunt ignoring jQuery when Uglifying?

I can't figure out why jQuery is being ignored when running my Grunt task. Here is what it looks like:
module.exports = function (grunt) {
// Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Concat
concat: {
js: {
src: [
'js/vendor/jquery.js',
'js/app/graph.js',
],
dest: 'app/build/js/app.js'
}
},
// Uglify
uglify: {
options: {
preserveComments: false
},
my_target: {
files: {
'app/build/js/app.min.js': [
'app/build/js/app.js'
]
}
}
});
};
When I check app.js, jQuery is part of it, but not in app.min.js. So I suspect something is wrong with the Uglify part.
github.com/gruntjs/grunt-contrib-clean This is not strictly necessary, jQuery should be included if that's all you've got. Do a test on the included site to be sure it's not just hiding somewhere in the uglified code.
I don't think your syntax is right, please try instead this:
uglify: {
development: {
options: {
preserveComments: false
},
files: {
'app/build/js/app.min.js': 'app/build/js/app.js'
}
}
And call it as: grunt.registerTask('default', ['concat', 'uglify:development']);
Not sure if this will help at all or if there even is any difference between the two, but you could try setting up your uglify config similarly to your concat config... e.g:
module.exports = function (grunt) {
// Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Concat
concat: {
js: {
src: [
'js/vendor/jquery.js',
'js/app/graph.js',
],
dest: 'app/build/js/app.js'
}
},
// Uglify
uglify: {
options: {
preserveComments: false
},
js: {
src: ['app/build/js/app.js'],
dest: ['app/build/js/app.min.js']
}
}
});
};
Also, I think you were missing an extra bracket

Implement const in grunt from terminal

I want to get const name from the terminal using grunt, and use it in uglify. This is what i want to happen:
uglify: {
options: {
sourceMap: true,
compress: {
global_defs: {
<myConst>: false
}
}
},
ugly: {
src: 'beautiful.js',
dest: 'ugly.js'
}
}
I use:
grunt --target=blabla
to pass the parameter, so myConst should be the input from the terminal (in this case blabla). I can't seem to find a way to put it instead of myConst (in code). Is it possible and how can i do it?
Since running grunt gives you the following command-line arguments in process.argv:
node
path_to_grunt_script
Couldn't you simply do something like:
module.exports = function(grunt) {
var compress_defs={},
args=process.argv.slice(2); // take all command line arguments skipping first two
// scan command line arguments for "--target=SOMETHING"
args.forEach(function(arg){
if(arg.match(/--target=(\S+)/)) { // found our --target argument
compress_defs[RegExp.$1]=false;
}
});
grunt.initConfig({
uglify: {
options: {
sourceMap: true,
compress: {
global_defs: compress_defs
}
},
ugly: {
src: 'beautiful.js',
dest: 'ugly.js'
}
});
};
Or better yet, rather than rolling-your-own, use a command-line processing library like minimist.

Grunt file does not complete

I have recently discovered grunt as it is used within an opensource project I have started to work on. Having not worked with grunt before I am struggling to see how it works, or in my case doesn't.
The grunt file is supplied by the project and I assume it works for everyone else. I have installed grunt and the necessary grunt modules have all installed in the "Node_modules" directory.
When running the grunt file the first process performs a number of concatenations and this seems to work fine. The concatenated files are created.
All of the other steps do not seem to execute. The files they are intended to create are not created. There is no error message displayed on the console when grunt is executed.
I'm stumped - anyone have any clues what might be the problem.
The grunt file is :
/*global module:false*/
module.exports = function(grunt) {
// Project configuration...
grunt.initConfig({
manifest: grunt.file.readJSON('chrome/manifest.json'),
concat: {
dist: {
src: ['chrome/js/requester/**/*.js'],
dest: 'chrome/js/requester.js'
},
requester_html: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/footer.html'
],
dest: 'chrome/requester.html'
},
requester_tester: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/footer.html',
'chrome/html/requester/tester.html'
],
dest: 'chrome/tester.html'
}
},
mindirect: {
dist: {
src: ['chrome/js/requester.js'],
dest: 'chrome/js/requester.min.js'
}
},
watch: {
requester_templates: {
files: ['chrome/html/requester/templates/*'],
tasks: ['handlebars'],
options: {
livereload: true
}
},
requester_js: {
files: ['chrome/js/requester/**/*.js'],
tasks: ['concat:dist'],
options: {
livereload: true
}
},
requester_html: {
files: ['chrome/html/requester/*', 'chrome/html/requester/modals/*', 'chrome/html/requester/loggers/*'],
tasks: ['concat:requester_html', 'concat:requester_tester'],
options: {
livereload: true
}
},
requester_css: {
files: ['chrome/css/**/*.scss'],
tasks: ['sass'],
options: {
livereload: true
}
}
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true
}
},
handlebars: {
compile: {
options: {
partialsUseNamespace: true,
namespace: 'Handlebars.templates',
processPartialName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
},
processName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
}
},
files: {
"chrome/html/requester/templates.js": "chrome/html/requester/templates/*"
}
}
},
sass: {
dist: {
files: {
'chrome/css/requester/styles.css': 'chrome/css/requester/styles.scss'
}
}
},
compress: {
main: {
options: {
archive: 'releases/v<%= manifest.version %>.zip'
},
files: [
{src: ['chrome/**', '!chrome/tests/**', '!chrome/manifest_key.json', '!chrome/tester.html'], dest: '/'}, // includes files in path and its subdirs
]
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-handlebars');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mindirect');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compress');
// Default task.
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
};
The output from the console is as follows :
Running "jshint:globals" (jshint) task
>> 0 files lint free.
Running "concat:dist" (concat) task
File "chrome/js/requester.js" created.
Running "concat:requester_html" (concat) task
File "chrome/requester.html" created.
Running "concat:requester_tester" (concat) task
File "chrome/tester.html" created.
Done, without errors.
Given that the tasks are defined like this:
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
the output you show is what you'd expect if you are running grunt without a task name. It runs the jshint and concat tasks.
If you want to run the tasks associated with package, then you have to run grunt package to run those tasks.
It looks like I did not understand "tasks" within grunt.
Instead of executing "grunt" which runs the "default" tasks, I had to execute "grunt package" which runs the tasks that I was interested in.
As Louis said, you have to specify the right task to run.
But you can also create or modify the tasks you have in order to make it simpler. In your example you may include package in the default task. Because concat task is already executed inside package, you may just replace it in the default task:
grunt.registerTask('default', ['jshint', 'package']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
and, in order to build your site, just type
grunt
both jshint and package tasks will be executed

Grunt task duplicate key

I have a grunt file with tasks and jshint giving me a warning for duplicate keys on below:
clean: ['public', 'build', 'css/main.css', 'css/print.css'],
clean : {
aftertest :['js/libs']
},
How can I make this in one key, so that by default it runs ['public', 'build', 'css/main.css', 'css/print.css']?
You should use different targets for this.
grunt.initConfig({
clean: {
build: ['public', 'build', 'css/main.css', 'css/print.css'],
aftertest: ['js/libs']
}
});
Then in your build alias you might want to use it like so:
grunt.registerTask('build', ['clean:build', 'stylus', 'jade', 'jshint']);
Whenever you have more than a single target for one task, it's best to explicitly name them so that you'll know, in the future, what each target's purpose is.
The error it's because the object you are passing to grunt.initConfig has two keys with the same name.
This is a Gruntfile.js example for gjslint task
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint', 'qunit']
},
gjslint: {
options: {
flags: [
'--nojsdoc'
],
reporter: {
name: 'console'
}
},
app: {
src: ['www/app/**/*.js']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-gjslint');
grunt.registerTask('build', 'Grunt build taskt...', function() {
grunt.log.write('you can log here some stuff...').ok();
});
};

Categories