How to concatenate and minify multiple CSS and JavaScript files with Grunt.js (0.3.x)


Tags: javascript,css,concatenation,minify,gruntjs

Problem :

Note: This question is only relevant for Grunt 0.3.x and has been left for reference. For help with the latest Grunt 1.x release please see my comment below this question.

I'm currently trying to use Grunt.js to setup an automatic build process for first concatenating and then minifying CSS and JavaScript files.

I have been able to successfully concatenate and minify my JavaScript files, although each time I run grunt it seems to just append to the file instead of overwriting them.

As for the minifying or even concatenating CSS, I have been unable to do this as of yet!

In terms of grunt CSS modules I have tried using consolidate-css, grunt-css & cssmin but to no avail. Could not get my head around how to use them!

My directory structure is as follows (being a typical node.js application):

  • app.js
  • grunt.js
  • /public/index.html
  • /public/css/[various css files]
  • /public/js/[various javascript files]

Here is what my grunt.js file currently looks like in the root folder of my application:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    concat: {
      dist: {
        src: 'public/js/*.js',
        dest: 'public/js/concat.js'
      }
    },
    min: {
      dist: {
        src: 'public/js/concat.js',
        dest: 'public/js/concat.min.js'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true
      },
      globals: {
        exports: true,
        module: false
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'concat min');

};

So just to summarise I need help with two questions:

  1. How to concatenate and minify all my css files under the folder /public/css/ into one file, say main.min.css
  2. Why does grunt.js keep on appending to the concatenated and minified javascript files concat.js and concat.min.js under /public/js/ instead of overwriting them each time the command grunt is run?

Updated 5th of July 2016 - Upgrading from Grunt 0.3.x to Grunt 0.4.x or 1.x

Grunt.js has moved to a new structure in Grunt 0.4.x (the file is now called Gruntfile.js). Please see my open source project Grunt.js Skeleton for help with setting up a build process for Grunt 1.x.

Moving from Grunt 0.4.x to Grunt 1.x should not introduce many major changes.



Solution :

concat.js is being included in the concat task's source files public/js/*.js. You could have a task that removes concat.js (if the file exists) before concatenating again, pass an array to explicitly define which files you want to concatenate and their order, or change the structure of your project.

If doing the latter, you could put all your sources under ./src and your built files under ./dest

src
├── css
│   ├── 1.css
│   ├── 2.css
│   └── 3.css
└── js
    ├── 1.js
    ├── 2.js
    └── 3.js

Then set up your concat task

concat: {
  js: {
    src: 'src/js/*.js',
    dest: 'dest/js/concat.js'
  },
  css: {
    src: 'src/css/*.css',
    dest: 'dest/css/concat.css'
  }
},

Your min task

min: {
  js: {
    src: 'dest/js/concat.js',
    dest: 'dest/js/concat.min.js'
  }
},

The build-in min task uses UglifyJS, so you need a replacement. I found grunt-css to be pretty good. After installing it, load it into your grunt file

grunt.loadNpmTasks('grunt-css');

And then set it up

cssmin: {
  css:{
    src: 'dest/css/concat.css',
    dest: 'dest/css/concat.min.css'
  }
}

Notice that the usage is similar to the built-in min.

Change your default task to

grunt.registerTask('default', 'concat min cssmin');

Now, running grunt will produce the results you want.

dest
├── css
│   ├── concat.css
│   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js

    CSS Howto..

    Dynamic HTML 3 layers nested quotes - how to do?

    How to style a GWT CaptionPanel?

    How to work with Action Link when using CSS

    How to replace HTML text with images using CSS content cross browser

    How to position an inner - inner tag at different position?

    How to remove border from appearing around the image?

    How to use base css file using twig

    How to center a child element in CSS, even if it is larger than the parent?

    CSS: How to make selectable boxes?

    how the highlighted text color and background is determined

    How can I center a div

    how do I float a div over a background image in a different div

    how to avoid from loading unnecessary javascript and css in page on codeigniter to improve the load time [closed]

    How can I add CSS to grandchild pages in an unordered list on Wordpress?

    How to select elements when there is a space in an HTML class

    How to make css style on Google custom search engine

    how to arrange the sequence of js and css files in webpage?

    How to make smooth animation in css?

    How to center align circles?

    How would you replicate these boxes in CSS?

    How to make elements stay within container?

    How to use css to set svg hover color?

    How should it work if I want a page to have a theme-roller (more or less like the jQuery themeroller)

    how to set width of a div in percentage minus certain pixels using javascript or css

    How to add a fade out at the end of this CSS animation?

    How to make contents vertical align inside div

    How to perfectly center a “plus” sign in a circle using CSS

    What is the correct css for the list of results to show correctly in this situation? [closed]

    How should I set this caption over my image using CSS?

    How to align div elements while using css tables