How can I access the Grunt config property site
to read the project.json
file at the path specified by the config property value?
grunt.registerTask('build', function(target) {
grunt.config('site', target);
grunt.task.run('foo:dist', 'bar:dist');
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.file.readJSON('./sites/' + grunt.config('site') + '/project.json')
});
grunt-cli:
grunt build:sitename
>> Error: Unable to read "./sites/undefined/project.json"
Using an example from the docs, I also tried this:
grunt.registerTask('global', 'site', function(prop, value) {
global[prop] = val;
});
grunt.registerTask('build', ['foo:dist', 'bar:dist']);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.file.readJSON('./sites/' + global.site + '/project.json')
});
grunt-cli:
grunt global:site:sitename
>> Error: Unable to read "./sites/undefined/project.json"
Update:
Using the @FelixKling answer as a guide, I've made some progress:
grunt.registerTask('build', function(target) {
grunt.config.set('target', target);
grunt.config.set('site', grunt.file.readJSON('./sites/' + grunt.config.get('target') + '/project.json'));
grunt.task.run('watch');
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.config.get('site'),
watch: {
sass: {
files: ['<%= site.dev %>/scss/*.scss'],
tasks: ['sass:dist']
}
},
sass: {
dist: {
files: {
'<%= site.dist %>/style.css': '<%= site.dev %>/scss/style.scss'
}
}
},
});
Now I'm able to read in the project.json
file successfully, and (somehow) it's even able to recognize when edits are made to watched files. But for some reason when it runs the sass:dist
task, I get this error: Warning: An error occurred while processing a template (Cannot read property 'dev' of undefined).
I'm not clear on how the watch
task is able to get the correct value for site
, but more importantly, I need to figure out a way to get that same value to the sass
task.
How can I access the Grunt config property site
to read the project.json
file at the path specified by the config property value?
grunt.registerTask('build', function(target) {
grunt.config('site', target);
grunt.task.run('foo:dist', 'bar:dist');
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.file.readJSON('./sites/' + grunt.config('site') + '/project.json')
});
grunt-cli:
grunt build:sitename
>> Error: Unable to read "./sites/undefined/project.json"
Using an example from the docs, I also tried this:
grunt.registerTask('global', 'site', function(prop, value) {
global[prop] = val;
});
grunt.registerTask('build', ['foo:dist', 'bar:dist']);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.file.readJSON('./sites/' + global.site + '/project.json')
});
grunt-cli:
grunt global:site:sitename
>> Error: Unable to read "./sites/undefined/project.json"
Update:
Using the @FelixKling answer as a guide, I've made some progress:
grunt.registerTask('build', function(target) {
grunt.config.set('target', target);
grunt.config.set('site', grunt.file.readJSON('./sites/' + grunt.config.get('target') + '/project.json'));
grunt.task.run('watch');
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.config.get('site'),
watch: {
sass: {
files: ['<%= site.dev %>/scss/*.scss'],
tasks: ['sass:dist']
}
},
sass: {
dist: {
files: {
'<%= site.dist %>/style.css': '<%= site.dev %>/scss/style.scss'
}
}
},
});
Now I'm able to read in the project.json
file successfully, and (somehow) it's even able to recognize when edits are made to watched files. But for some reason when it runs the sass:dist
task, I get this error: Warning: An error occurred while processing a template (Cannot read property 'dev' of undefined).
I'm not clear on how the watch
task is able to get the correct value for site
, but more importantly, I need to figure out a way to get that same value to the sass
task.
1 Answer
Reset to default 18initConfig
and grunt.file.readJSON
run before your task runs. It seems like what you need are template strings and you can only call grunt.file.readJSON
when you actually have the target name.
For example:
grunt.registerTask('build', function(target) {
grunt.config.set('target', target);
grunt.config.set('site', grunt.file.readJSON(grunt.config.get('path'));
grunt.task.run('foo:dist', 'bar:dist');
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
path: './sites/<%= target %>/project.json'
});
More info: http://gruntjs.com/api/grunt.config
Regarding your update: You are basically making the same mistake again as you did in your first example. You are trying to access the config site
before it was set.
You have to understand that the initialization step, i.e. grunt.initConfig
takes place before any task related code runs:
Initialize config -> Run task
Lets look at grunt.initConfig
in isolation:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
site: grunt.config.get('site'),
});
This is the initialization step, which happens before everything else. The argument passed to initConfig
, the configuration object, is evaluated first. What you are trying to do here is access the config options site
, before the config was even created. I hope you recognize that this doesn't make sense.
Maybe it helps you to understand the process if you put grunt.initConfig
at the very top, before you register any tasks.
The solution:
I think what you actually might be after are command-line arguments, with which you can control which site to build. See grunt.option
for more information.
For example:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
sass: {
files: ['<%= site.dev %>/scss/*.scss'],
tasks: ['sass:dist']
}
}
});
grunt.config.set('site', grunt.file.readJSON('./sites/' + grunt.option('site') + '/project.json'));
And then you run the task with
grunt watch --site=somesite
grunt.file.readJSON('./sites/' + global.site + '/project.json')
runs,global.site
doesn't exist yet since theglobal
task didn't run yet. Check my answer again, I fixed what was wrong. – Felix Kling Commented Apr 10, 2014 at 19:45