3

I have a project where I'm using grunt to process my Js and SASS files.

At the moment, when I need to process something, I need to call all the tasks inside my gruntfile.js even if I want to change only one module, or only the SASS file.

Is there a way to create a custom task, to run only the sass part, and another one to create only a module process, where I can call this task from the prompt?

This is what I tried, without success:

    module.exports = function(gruntHome) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        /* @CONCAT */
        concat: {
            home : {
                src: 'src/app/component/home/*.js',
                dest: 'src/app/component/home/concat/concat_config.js'
            }
        },

        /* @ANNOTATE */
        ngAnnotate: {
            options: {
                add: true
            },
            home: {
                files: {
                    'src/app/component/home/concat/concat_config.js': 'src/app/component/home/concat/concat_config.js'
                }
            }
        },

        /* @UGLIFY */
        uglify: {
            home: {
                src:  'src/app/component/home/concat/concat_config.js',
                dest: 'app/component/home/home.min.js'
            }
        }
    });


    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-ng-annotate');

    grunt.registerTask('gruntTask', ['concat', 'ngAnnotate', 'uglify']);
};

If it's not possible, is there any other way to achieve this objective? Because my gruntfile.js is huge, and sometimes it takes a lot of time to process, even if I don't need to process everything.


Edit:

This link here is a related question I made following the steps provided on this question. It will solve some possible issues you have when trying to do what i did here. Hope it can help other people.

Community
  • 1
  • 1
celsomtrindade
  • 4,501
  • 18
  • 61
  • 116

1 Answers1

7

Here is how, you can organise your grunt tasks :

  • config : Default tasks
  • register : Alias tasks which call multiple default tasks

Some rules that you have to respect :

  • the name of your file must be the same name of your task (E.g : ngAnnotate.js -> task : ngAnnotate)
  • group your configurations tasks by grunt plugins in one file. Don't mix grunt-plugins in configuration tasks, Register tasks are there for this job.
  • name of configuration task and register tasks are shared then you can't set a home configuration task and a home register task because when you call it with grunt home, grunt isn't able to know the task that you are refering to.
├── Gruntfile.js
└── grunt
    ├── config
    │   ├── sass.js
    │   ├── concat.js
    │   └── uglify.js
    └── register
        ├── GroupOfTasks.js
        └── AnotherGroupOfTasks.js

Your Gruntfile.js will load and configure all tasks in grunt/config and grunt/register folder with this code :

module.exports = function(grunt) {


    // Load the include-all library in order to require all of our grunt
    // configurations and task registrations dynamically.
    var includeAll;

    try {
        includeAll = require('include-all');
    }
    catch (e0) {
        console.error('Could not find `include-all` module.');
        console.error('Skipping grunt tasks...');
        console.error('To fix this, please run:');
        console.error('npm install include-all --save-dev');
        console.error();
    }

    /**
     * Loads Grunt configuration modules from the specified
     * relative path. These modules should export a function
     * that, when run, should either load/configure or register
     * a Grunt task.
     */
    function loadTasks(relPath) {
        return includeAll({
                dirname: require('path').resolve(__dirname, relPath),
                filter:  /(.+)\.js$/
            }) || {};
    }

    /**
     * Invokes the function from a Grunt configuration module with
     * a single argument - the `grunt` object.
     */
    function invokeConfigFn(tasks) {
        for (var taskName in tasks) {
            if (tasks.hasOwnProperty(taskName)) {
                tasks[taskName](grunt);
            }
        }
    }

    // Load task functions
    var taskConfigurations  = loadTasks('./grunt/config'),
        registerDefinitions = loadTasks('./grunt/register');

    // Run task functions to configure Grunt.
    invokeConfigFn(taskConfigurations);
    invokeConfigFn(registerDefinitions);

};

Your config task should look like that (E.g : sass.js) :

module.exports = function(grunt) {
    grunt.config.set('sass', {
        dev: {
            options: {
                sourceMap: false
            },
            files: {
                'main.css': 'main.scss'
            } 
        }
    });

    grunt.loadNpmTasks('grunt-sass');
};

You will be able to run config task with grunt sass to run all sass task or grunt sass:dev to run only one task.

And a register task should look like that (E.g: SassAndConcat task to run sass and concat task) :

module.exports = function(grunt) {
    grunt.registerTask('SassAndConcat', [
        'sass:dev',
        'concat:dev',
    ]);
};

And now you will be able to run grunt SassAndConcat.

If you understand that, you will be able to run your grunt tasks more efficiently by running the right task at the right time.

Don't forget to install include-all NPM module to require all of our grunt configurations and task registrations dynamically.

Louis Barranqueiro
  • 10,058
  • 6
  • 42
  • 52
  • Nice! Very nice, i think i got it. Just one more thing. How do i call it from the prompt? Right now i just type 'grunt' and it run everything. Should i create multiple modules, with a name of 'sassGrunt', for example, and call it on the prompt 'sassGrunt' ? – celsomtrindade Nov 19 '15 at 14:18
  • 2
    I have updated my anwser with information how to run config and register tasks. – Louis Barranqueiro Nov 19 '15 at 14:29
  • Ok, thanks for your help. It will save me a lot of time! And improve my workflow a lot. – celsomtrindade Nov 19 '15 at 14:30
  • your welcome :) Check this repository, if you wanna see a full example with many tasks : https://github.com/LouisBarranqueiro/tranquilpeak-hexo-theme – Louis Barranqueiro Nov 19 '15 at 14:33
  • Yes! It helped me a little, but @LouisBarranqueiro, can you take a look at this git: https://github.com/celsomtrindade/gruntTest It's the files I'm using to try this solutions. I have 2 proccess, almost the same. 'Sass' and 'Inicio'. 'sass' works fine, but 'inicio' says: `Task 'inicio' not found` Any idea why? – celsomtrindade Nov 19 '15 at 19:17
  • I did it @LouisBarraqueiro, its here: http://stackoverflow.com/questions/33813073/task-not-found-using-grunt would you mind taking a look at it? – celsomtrindade Nov 19 '15 at 19:49
  • 1
    @LouisBarranqueiro Excellent answer - it appears you used SailsJS Gruntfile.js code and organization, as it is pretty much the same? Anyway - I was wondering, I'd like to use jit-grunt to significantly reduce load time of this approach for processors on file watches. However, based on time sampling with time-grunt and `grunt -v myprocess:dev`, all tasks are loaded! Any ideas on how to improve this approach with jit-grunt to only load required tasks? – ryanm Mar 26 '16 at 20:10
  • yeah, this architecture is based on sails.js. Ask this on a new question, i'm gonna check it :) – Louis Barranqueiro Mar 26 '16 at 20:16