Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access Grunt config data within initConfig()

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.

like image 981
cantera Avatar asked Apr 10 '14 18:04

cantera


People also ask

What is Grunt config?

config. Access project-specific configuration data defined in the Gruntfile . Note that any method marked with a ☃ (unicode snowman) is also available directly on the grunt object, and any method marked with a ☆ (white star) is also available inside tasks on the this object.

When a task is run Grunt looks for its configuration under a?

When a task is run, Grunt looks for its configuration under a property of the same name. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets." In the example below, the concat task has foo and bar targets, while the uglify task only has a bar target.

Is Grunt still used?

The Grunt community is still going strong and both tools look like they're going to be around for a while yet. I should mention that another up and coming alternative to task runners like Grunt and Gulp is simply using npm scripts with command-line tools.


1 Answers

initConfig 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
like image 90
Felix Kling Avatar answered Oct 17 '22 07:10

Felix Kling