Skip to main content

Installing Node JS and Grunt

This tutorial focuses on installing the platform, and provides resources for using Grunt.

This was originally from May 8, 2013 and has been re-written for the latest version of Node and Grunt.

Step 1: Install Node

If you installed with homebrew, skip to Proxy or Grunt step(s)

Otherwise, Download the latest stable binary from nodejs.org. On production servers is recommended to use the latest STABLE version. The default settings will be fine.

Verify your path as per installer message: Make sure that /usr/local/bin is in your $PATH.

Note: I found this Stackoverflow post useful: Set environment variables: bash profile. Please note to check that the path in the installer is shown in case it differs between versions. For my install, the path was correctly set.

Step 2: Use a proxy with node

If you require the use of a proxy with node, you set it with the below (this to this post How to setup Node.js and Npm behind a corporate web proxy).

npm config set proxy http://proxy.example.org:8080
npm config set https-proxy http://proxy.example.org:8080

Step 3: Grunt set-up

Installing Grunt on your machine globally.

This section uses grunt 0.4.x

Grunt JS is installed by what NodeJS refers to as NPM, or Node Package Manager. To install Grunt from NPM, you will need to use the command line.

Type following command into the terminal:

npm install -g grunt-cli

Create a package.json file

Go into your project directory, and run the below command. You can use the default settings, as the text file will be edited. My output is below.

npm init

Open your favorite text editor, and edit the file "package.json" replace the text so it will fit your project:

{
  "name": "demo-project",
  "version": "0.0.1",
  "author": "Jennifer Tesolin"
}

Now, using the terminal, run the below command in your project directory:

npm install grunt --save-dev

This will install grunt locally in your package folder. If you open your package.json, you will find a new section added:

"devDependencies": {
    "grunt": "~0.4.1"
}

Associating plugins with Grunt/package.json

Run the below command to use the plugin npm.

npm install grunt-contrib --save-dev

Create your grunt file

In your text editor, create a file called "Gruntfile.js" and save this into your project directory. A sample copy is below:

module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({

    });

    // Load call for plugins

    // Default task(s).

};

Sample Grunt file

TThe various commands you can run in your terminal are as follows:

  1. grunt images: Will make your images web ready, and create sizes for different screens.
  2. grunt css: will convert sass to css, then run through a linter, post css and finally concatenate your css files
  3. grunt jscript: runs jshint
  4. grunt dev: will run the jscript, and css grunt commands, and will open up watch to monitor changes.
  5. grunt build: will run everything and create a build you can use for production.
module.exports = function(grunt) {

  'use strict';

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    sass: {
      dist: {
        options: {
          style: 'expanded', /**human readable */
          sourcemap: 'none',
        },
        files: {
          'css/style.css': 'sass/style.scss'
        }
      }
    },
    csslint: {
        strict: {
            src: ['css/style.css']
        },
        lax: {
            options: {
                csslintrc: '.csslintrc' //just check for css errors that would stop code
            },
            src: ['css/style.css']
        }
    },
    concat: {
      css: {
          src: ['node_modules/normalize.css/normalize.css', 'css/style.css'],
          dest: 'css/style.css'
      }
    },
    postcss: {
      options: {
        processors: [
          require('pixrem')(),
          require('autoprefixer')({browsers: 'last 2 versions'})
        ]
      },
      dist: {
        src: 'css/style.css',
        dest: 'css/style.css'
      }

    },
    cssmin : {
        css:{
            src: 'css/style.css',
            dest: 'css/style.min.css'
        }
    },
    uglify: {
      options: {
        banner: '/*
 <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> 
*/
'
      },
      build: {
        files: {
          'js/scripts.min.js': ['js/*.js', '!js/*.min.js']
        }
      }
    },
    jshint: {
      files: ['Gruntfile.js', 'js/*.js', '!js/*.min.js'],
      options: {
        jshintrc: '.jshintrc',
        ignores: '.jshintignore'
      },
    },
    htmlmin: {                                     // Task
      dist: {                                      // Target
        options: {                                 // Target options
          removeComments: true,
          collapseWhitespace: true
        },
        files: [
          {
            expand: true,     // Enable dynamic expansion.
            cwd: 'src/',      // Src matches are relative to this path.
            src: ['**/*.html'], // Actual pattern(s) to match.
            dest: 'dist/',   // Destination path prefix.
          },
        ],
      }
    },

    imagemin: {
        png: {
          options: {
            optimizationLevel: 7
          },
          files: [
            {
              expand: true,
              cwd: 'img/',
              src: ['**/*.png'],
              dest: 'img/compressed/',
              ext: '.png'
            }
          ]
        },
        jpg: {
          options: {
            progressive: true
          },
          files: [
            {
              expand: true,
              cwd: 'img/',
              src: ['**/*.jpg'],
              dest: 'img/compressed/',
              ext: '.jpg'
            }
          ]
        }
      },
    responsive_images: {
      myTask: {
        options: {
          sizes: [{
              name: 'header-320',
              width: 320
            },
            {
              name: 'header-640',
              width: 640
            },
            {
              name: 'header-768',
              width: 768
            },
            {
              name: 'header-1024',
              width: 1024
            },
            {
              name: 'header-1366',
              width: 1366
            },
            {
              name: 'header-1920',
              width: 1920
            },
            {
              name: "header-2560",
              width: 2560
          }]
        },
        files: [{
          expand: true,
          cwd: 'img/',
          src: ['**.{jpg,gif,png}'],
          dest: 'img/resize'
        }]
      }
  },
  clean: {
    build: {
      src: [ 'build' ]
    },
    stylesheets: {
      src: [ 'build/**/*.css', '!build/application.css' ]
    },
    scripts: {
      src: [ 'build/**/*.js', '!build/application.js' ]
    },
    images:{
      src: [ 'img/compressed/**/', 'img/resize/**/']
    }
  },
  watch: {
    gruntfile: {
      files: 'Gruntfile.js',
      tasks: ['jshint'],
    },
    css: {
      files: ['sass/*.scss'],
      tasks: ['sass', 'csslint:lax', 'postcss', 'concat:css']
    },
    js: {
      files: ['js/*.js','!js/*.min.js'],
      tasks: ['jshint'/*,'concat:js','uglify'*/]
    }
  },
  copy: {
      build: {
        cwd: 'source',
        src: [ '**' ],
        dest: 'build',
        expand: true
      },
    }

  }); //end grunt config

  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-responsive-images');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');

  grunt.registerTask('images', ['clean:images', 'responsive_images','imagemin']);
  grunt.registerTask('css', ['sass', 'csslint:lax', 'postcss','concat:css']);
  grunt.registerTask('jscript', ['jshint']);
  grunt.registerTask('dev', ['jscript', 'css','watch']);
  grunt.registerTask('build', ['clean', 'copy']);

};

Re-install devDependencies or dependencies

With the new package.lock file, npm update may not get the latest version if its a major update. Use the below to pick up the latest package. With Thanks to stack overflow (please let me know if you see the post, it was deleted from my notes).

npm uninstall jshint
npm cache clean -f
npm install --save-dev jshint

Resources: