How can I make 'grunt less' automatically run autoprefixer?

7.6k views Asked by At

I have a working Gruntfile with less and autoprefixer. I also have 'grunt watch' working fine.

Before I was using autoprefixer, I was using less mixins for vendor prefixes. Running 'grunt less' would build working CSS with all my prefixes.

Now I have autoprefixer, but if I want to do a once-off build of my styles, I now have to run 'grunt less' then 'grunt autoprefixer' to get working CSS with prefixes.

How can I modify 'grunt less' so it build working, prefixes less again?

I've read the docs, and I know I could add an additional task to do both these things. However:

  • 'grunt less' now doesn't have usable output. A task should always produce usable output.
  • I don't want to have to tell other people that 'grunt less' doesn't produce usable output
  • An additional task should not be required to replace one that doesn't work

I.e., I just want grunt less to produce working CSS (with prefixes).

module.exports = function(grunt) {

  // Load Grunt tasks declared in the package.json file
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

  // Configure Grunt
  grunt.initConfig({

    less: {
      development: {
        options: {
          paths: ["./less"],
          yuicompress: false
        },
        files: {
          "./public/css/style.css": "./public/less/style.less"
        }
      }
    },

    autoprefixer: {
      development: {
        browsers: ['last 2 version', 'ie 9'],
        expand: true,
        flatten: true,
        src: 'public/css/*.css',
        dest: 'public/css'
      }
    },

    watch: {
      less: {
        files: ["./public/less/*"],
        tasks: ["less", "autoprefixer:development"],
        options: {
          livereload: true
        }
      }
    },

  });


};
2

There are 2 answers

6
Ben On BEST ANSWER

Grunt can't do what you describe in the question as tasks do not know about each other inherently. You have to glue tasks together using aliases, (easy) or functions (for when you want a bit more control), but there's no way of modifying the way one of these tasks behaves without changing the source.

As an example, you could fork grunt-contrib-less and add the code to run the auto prefixing directly into the task, around here: https://github.com/gruntjs/grunt-contrib-less/blob/master/tasks/less.js#L69 - inject this line here https://github.com/nDmitry/grunt-autoprefixer/blob/master/tasks/autoprefixer.js#L56 and then use your fork instead of the official plugin.

The easiest and best way is to register a new task that does the job of these two tasks but in the one command, i.e:

grunt.registerTask('buildless', ['less', 'autoprefixer']);

I do this with all my own tasks - SASS compilation, JS concat + uglify, webfont generation etc. Just tell the others in your team to run those tasks and not grunt less or grunt autoprefixer on their own.

Better still, use my Grunt plugin available tasks. With this (and the filter config) you will be able to produce a trimmed down list of tasks whenever someone runs grunt availabletasks although I prefer to alias this with tasks for quicker typing. If you're like me and have been bitten by the automation bug (and have registered loads of plugins in your Gruntfile), this can really help a newcomer to the project with which tasks should be run.

1
Dunaevsky Maxim On

For using autoprefixer as plugin for LESS, you must install npm-package less-plugin-autoprefix:

npm install grunt-contrib-less less-plugin-autoprefix --save-dev

Gruntfile.js

module.exports = function(grunt) {
  "use strict";
  var gruntConfig = {
    less : {
      options : {
        plugins : [ new (require('less-plugin-autoprefix'))({browsers : [ "last 2 versions" ]}) ]
      },
      main : {
        files: {
          'src/css/desktop/bootstrap-theme.css' : 'src/less/desktop/bootstrap-theme.less',
          'src/css/desktop/company.css' : 'src/less/desktop/company.less',
          'src/css/desktop/index.css' : 'src/less/desktop/index.less',
          'src/css/desktop/login.css' : 'src/less/desktop/login.less'
        }
      }
    }
  };

  grunt.initConfig(gruntConfig);
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.registerTask('default', [ 'less' ]);
};