load-grunt-configs

by creynders

Allows splitting your grunt task configuration into separate files

125 Stars 15 Forks Last release: Not found MIT License 88 Commits 13 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

load-grunt-configs

npm version Build Status

Loads grunt task configurations from separate files.

Grunt files tend to grow fast due to big amount of tasks and their configuration objects. This module allows you to split your Grunt task configuration objects into separate files any way you choose. There are similar modules that allow you to the same, but with

grunt-load-configs
you can configure targets for a single task in multiple files.

This means you no longer need to group all task targets into a single file, but can split them up according to their task dependencies.

Example

you use the

watch
task to recompile your
.scss
files, but also to lint your source
.js
whenever one has changed. Typically you'd add a single
watch
configuration object to configure this, but with
load-grunt-configs
you can split these into several files and group all task targets together whenever it makes sense:
//config/css.js

module.exports.tasks = { watch : { scss : { files : ['app/sass/*.{scss,sass}'], tasks : ['compass:source'] } }, compass : { source : { //configuration settings } } };

//config/lint.js

module.exports.tasks = { watch : { lint : { files : ['app/{,/}.js'] tasks : ['jshint:source'] } }, jshint : { source : { //configuration settings } } }

Getting Started

load-grunt-configs
supports the loading of grunt config files in following formats:
  • json
  • js modules
  • coffee modules
  • cson
  • yaml

Though the provided examples are mainly for

json
files and
js
modules, the same applies to the other formats. You can find examples of all formats in the
config
directory of this project.

Migrating your configuration from a big, fat grunt file

I wrote a small utility Grunt task which takes your full-blown Grunt configuration and automatically splits it into separate files: grunt-generate-configs (supports all formats

load-grunt-configs
does too)

You only need to do this once:

$ npm install grunt-generate-configs -g
# cd to your project directory containing the Gruntfile
$ generate_configs

This will create a separate

.json
file for each task inside a
config
directory. (See grunt-generate-configs for all options: a different format, directory, etc.)

Next you need to delete the full configuration object in your

Gruntfile.js
.

Then ...

Automatically loading the config files

Install the load-grunt-configs module with:

npm install load-grunt-configs --save-dev
// Gruntfile.js
module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-jshint');

//loads the various task configuration files
var configs = require('load-grunt-configs')(grunt);
grunt.initConfig(configs);

grunt.registerTask('default', ['jshint']);

}

load-grunt-configs
supports the loading of config files as
.js
,
.json
,
.yaml
or
.coffee
. You can even mix and match if you want. Take a look at the
config
folder of this project to see examples for all formats.

To configure the

jshint
task for example, add a file
config/jshint.json
(in case you didn't use the generator to automatically generate it):
{
    "gruntfile" : {
        "src" : "Gruntfile.js"
    }
}

By default the basename (without the file extension) of the filename will be used to recognize which task is being configured.

jshint
in the above example.

Advanced usage

Using node modules for configuration

Task configuration is also possible through node modules, either by exposing an object:

//config/jshint.js
module.exports = {
     gruntfile : {
         src : "Gruntfile.js"
     }
 }

Or by exposing a function which returns an object:

//config/jshint.js
module.exports = function(grunt, options) {
     return {
         gruntfile : {
             src : "Gruntfile.js"
         }
     }
 }

Declaring multiple task configurations in one file

If the returned object contains a

tasks
key, its value will be assumed to be a name/configuration pair mapping:
//config/grunt.json
{
    "tasks" : {
        "jshint" : {
            "gruntfile" : {
                "src" : "Gruntfile.js"
            }
        },
        "watch"  : {
            "gruntfile" : {
                "src" : "Gruntfile.js",
                "tasks" : ['jshint:gruntfile']
            }
        }
    }
}

The above will configure both the

jshint
and
watch
tasks.

Split multi-task configurations

But wait, there is more! You can split multi-task configurations in multiple files as well. For instance if you have the above

config/grunt.json
file and you add the following file:
//config/test.json
{
    "tasks" : {
        "jshint" : {
            "test" : {
                "src" : ["test/**/*.js"]
            }
        }
        "watch" : {
            "test" : {
                "src" : ["test/**/*.js"],
                "tasks" : ['jshint:test']
            }
        }
    }
}

Now both

watch
and
jshint
tasks have two targets:
gruntfile
and
test
.

Passing values to the configuration files

If you declare a function in your config file it receives two arguments:

grunt
and
options
, which allows you to use the
grunt
instance and pass values. In this way, you can declare custom tasks on your config files (especially useful if you follow the "Split multi-task configurations" method above).
// Gruntfile.js
var options = {
    paths : {
        jshintrc : '.jshintrc'
    }
};

var configs = require('load-grunt-configs')(grunt, options);

// config/jshint.js module.exports = function(grunt, options) { grunt.registerTask('custom', ['jshint:gruntfile']);

return {
    options : {
        jshintrc : ''
    },

    gruntfile : {
        src : 'Gruntfile.js'
    }
};

}

Task name prefixed task targets

As a convenience method you can prefix your task targets with the task name, separated by a ":" (colon). This allows you to do this:

//config/monitor.js
module.exports.tasks = {
    "watch:test" : {
        src : ["test/**/*.js"],
        tasks : ['jshint:test']
    },
    "watch:gruntfile" : {
        src : "Gruntfile.js",
        tasks : ['jshint:gruntfile']
    }
}

This makes it easier when in the future you'd like to move the

watch:gruntfile
task configuration to another file for instance.

Troubleshooting

The tradeoff of a neatly organized Grunt configuration is sometimes having trouble locating which file is declaring exactly what.

In that case, or if loading some file is causing an error and aborting your Grunt process, you can always run:

grunt --verbose

A nice log of processed files and loaded tasks/targets will help you locate the problems. Here's the output when running on this very repo:

Loading grunt configs via "load-grunt-configs" from 6 file(s).
Loading config/connect.js...is fn(), invoking...OK
+ connect: [options, docs]

Loading config/jshint.json...OK

  • jshint: [options, lib, build, test]

Loading config/watch.js...is fn(), invoking...OK

  • watch: [lib, build, test, docs, livereload]

Loading config/clean.coffee...is fn(), invoking...OK

  • clean: [config, tmp]

Loading config/nodeunit.yml...OK

  • nodeunit: [load_grunt_configs]

Loading config/markdown.cson...OK

  • markdown: [docs]

Options

You can modify the directory in which the configuration files need to reside:

//Gruntfile.js
var options = {
    config : {
        src : "options/*.js"
    }
};

configs = require('load-grunt-configs')(grunt, options);

Will search for the configuration files in an

options
directory.

You can also supply a customizer function for the configuration merging:

//Gruntfile.js
var options = {
    config : {
        mergeCustomizer : function(a, b) {
            return Array.isArray(a) ? a.concat(b) : undefined;
        }
    }
};

configs = require('load-grunt-configs')(grunt, options);

See lodash#merge for more information on the customizer function.

Examples

You can take a look at the

Gruntfile.js
and the configuration files in the
config
directory of this project. Or browse through the 3 demos in this repository:
  1. Configuration per task. Each task configuration goes into its own file:
    watch.js
    ,
    jshint.js
    ,
    concurrent.js
    , ...
  2. A single configs file. The entirety of the grunt configuration is moved to a seperate file (
    grunt.js
    ). This way the Gruntfile.js only contains task declarations.
  3. Configuration by task type. Task target configurationsare spread over multiple files and grouped wherever logically it makes sense. E.g.
    build.js
    ,
    serve.js
    ,
    test.js
  4. Various formats: See the
    config
    directory of this project.

All various possibilities

  • json with a single task configuration: E.g. configures
    jshint
    task in
    config/jshint.json
    (task name extracted from file name)
{
    "gruntfile" : {
        "src" : "Gruntfile.js"
    }
}
  • json with multiple task configurations: E.g. configures
    jshint
    and
    watch
    tasks in
    config/.json
    . Note the top-most key "tasks" here, it alerts the module not to extract the task name from the file name.
{
    "tasks" : {
        "jshint" : {
            "gruntfile" : {
                "src" : "Gruntfile.js"
            }
        },
        "watch" : {
            "gruntfile" : {
                "src" : "Gruntfile.js",
                "tasks" : ["jshint:gruntfile"]
            }
        }
    }
}
  • json with multiple task configurations using task prefixed targets: E.g. configures
    jshint
    and
    watch
    tasks in
    config/.json
{
    "tasks" : {
        "jshint:gruntfile" : {
            "src" : "Gruntfile.js"
        },
        "watch:gruntfile" : {
            "src" : "Gruntfile.js",
            "tasks" : ["jshint:gruntfile"]
        }
    }
}
  • js with single task configuration as an object: E.g. configures
    jshint
    task in
    config/jshint.js
module.exports = {
     gruntfile : {
         src : "Gruntfile.js"
     }
};
  • js with single task configuration as a function: E.g. configures
    jshint
    task in
    config/jshint.js
module.exports = function(grunt, options) {
    return {
        gruntfile : {
            src : "Gruntfile.js"
        }
    };
};
  • js with multiple task configurations as an object: E.g. configures
    jshint
    and
    watch
    task in
    config/.js
module.exports.tasks = { //note the `tasks` export here [!]
    jshint : {
        gruntfile : {
            src : "Gruntfile.js"
        }
    },
    watch : {
        gruntfile : {
            src : "Gruntfile.js",
            tasks : ['jshint:gruntfile']
        }
    }

};

  • js with multiple task configurations as a function: E.g. configures
    jshint
    and
    watch
    task in
    config/.js
module.exports = function(grunt, options) {
    return {
        tasks : {
            jshint : {
                gruntfile : {
                    src : "Gruntfile.js"
                }
            },
            watch : {
                gruntfile : {
                    src : "Gruntfile.js",
                    tasks : ['jshint:gruntfile']
                }
            }
        }
    };
};
  • js with multiple task configurations as an object using task prefixed targets: E.g. configures
    jshint
    and
    watch
    task in
    config/.js
module.exports.tasks = { //note the `tasks` export here [!]
    "jshint:gruntfile" : {
        src : "Gruntfile.js"
    },
    "watch:gruntfile" : {
            src : "Gruntfile.js",
            tasks : ['jshint:gruntfile']
    }
};
  • js with multiple task configurations as a function using task prefixed targets: E.g. configures
    jshint
    and
    watch
    task in
    config/.js
module.exports = function(grunt, options) {
    return {
        tasks : {
            "jshint:gruntfile" : {
                src : "Gruntfile.js"
            },
            "watch:gruntfile" : {
                src : "Gruntfile.js",
                tasks : ['jshint:gruntfile']
            }
        }
    };
};

Changelog

  • v0.4.3:
    • Update dependencies
    • Swap cson-safe to cson-parser
    • add
      mergeCustomizer
  • v0.4.2: Explicit bailing on invalid task config
  • v0.4.1: Better verbose output
  • v0.4.0: Switch to cson-safe for parsing cson
  • v0.3.3:
    • Add cson support
    • Loads yaml files with safeLoad
  • v0.3.2:
    • fixes incorrect grunt dep
    • adds coffee config file
    • adds yaml support
  • v0.3.1:
    • fixes incorrect overwrite of passedin options for this task
    • adds tests
    • Updates examples and adds all various configuration possibilities
  • v0.3.0:
    • disallows function declaration anywhere else than as direct export
    • extracts taskname regardless of file extension
  • v0.2.0:
    • adds coffeescript support
    • adds parsing of taskname prefixed task targets
    • fixes incorrect handling of functions at task config leaves
  • v0.1.0:
    • adds "by type' demo
    • adds "by taskname" demo
    • adds "single file" demo
    • Initial commit

Contributors

License

Copyright (c) 2014 Camille Reynders Licensed under the MIT license.

With special thanks to @stefanpenner and @thomasboyt. This module is based on the ideas in Thomas' excellent tutorial: http://www.thomasboyt.com/2013/09/01/maintainable-grunt.html

Analytics

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.