Getting started with Grunt.js

Dennis Schipper
Frontend Weekly
Published in
7 min readSep 12, 2016

Grunt is a task runner to help automate front end development & save time. I use it to speed up coding designs into static pages for sharing with developers. There’s plenty of alternatives with different (and similar) use cases, like gulp or webpack, but grunt works for me.

We’ll start by installing node & grunt, then get the scss and html-build modules working. Last, we’ll set up a local server that with track changes to your files and refresh the browser window.

We’ll start with a simple set of requirements:

  • Scss files will be rendered to css.
  • Html files will support templates/partials.
  • Any changes to our source files will automatically trigger a refresh on our open browser window.

First, install node.js

Grunt needs node to work, so we’ll start with that. Download the current version (not the LTS) and install it. Node comes with npm, the node package manager, which we’ll use to install modules.

With node working, we can install grunt. Open up a terminal window and type in the command below

sudo npm install -g grunt-cli

The “-g” in the command above will install grunt globally, so we can use it everywhere. Sudo will run the command as an administrator — you can skip the “sudo” part of it if on windows.

Now create a folder for your project — I named mine “gruntproject”, but you can use anything. Open a terminal window to that folder, then type “npm init” & press enter to skip all the questions. This will create a “package.json” file, which npm uses to keep track of installed modules.

With our project ready, we can install the first module, grunt itself.

npm install grunt --save-dev

The “save-dev” option will install grunt locally on a folder called “node_modules”, and add it to our package.json file.

Now we can create our gruntfile . That’s the main set of instructions for grunt. Create a file in your directory called Gruntfile.js and copy the following into it.

module.exports = function(grunt) {

grunt.initConfig({

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

This is pretty minimal, but enough to confirm that grunt works. Still in the project folder, type “grunt” in your terminal. You should get a line saying “Done.” and no errors.

Running grunt with no tasks.

With grunt working, we can get started with the first requirement — compiling scss to css. We’ll have to create some new folders to hold our files. Run the following commands on the terminal to create the folders & files we need.

mkdir src
mkdir src/scss
mkdir dev
mkdir dev/css
touch src/scss/styles.scss
touch src/index.html
mkdir src/templates
touch src/templates/header.html

“mkdir” is the command to create a folder, and “touch” to create a file. Our file structure should look something like this now.

Your folder structure should look similar to this.

Now let’s install the grunt-contrib-sass module.

npm install grunt-contrib-sass --save-dev

Along with grunt-contrib-sass, we’ll need to install the sass gem locally. If you’re on osx or linux you should be able to just run the following command.

gem install sass

On windows, install ruby before you run the command above.

We installed the module, but need to let grunt know that it’s there. Let’s update our gruntfile to look like the code below.

module.exports = function(grunt) {grunt.initConfig({sass: {
dist: {
files: {
"dev/css/styles.css" : "src/scss/styles.scss"
}
}
}
});grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('default', []);
};

There’s two parts we need to take a better look at. The loader near the bottom of the file (grunt.loadNpmTasks) makes sure that grunt knows the plugin is there.

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

The rest is configuring the task. Sass will open the file in “src/scss/styles.scss”, compile it to css, then save it in “dev/css/styles.css”.

sass: {
dist: {
files: {
"dev/css/styles.css" : "src/scss/styles.scss"
}
}
}

We can now add some basic styles into styles.scss and make sure that the task works like it should. Open styles.scss and add the code below to it.

body {
background: #f9f9f9;
text-align: center;
h1 {
font-weight: 100;
}
}

In the terminal, type “grunt sass”. Grunt should go through the scss files, and output them in “/dev/css/styles.css”.

Adding templates to html files

With our stylesheets working, we can work on the html files. We’ll use grunt-html-build to add templates to our files. html-build is a versatile tool and can do more than just templating, but that’s all we need it to do for now. Install the plugin with:

npm install grunt-html-build --save-dev

Now update Gruntfile.js

module.exports = function(grunt) {grunt.initConfig({    sass: {
dist: {
files: {
"dev/css/styles.css" : "src/scss/styles.scss"
}
}
},
htmlbuild: {
dist: {
src: './src/index.html',
dest: './dev/',
options: {
beautify: true,
relative: true,
basePath: false,
sections: {
layout: {
header: './src/layout/header.html'
}
},
}
}
},
}); grunt.loadNpmTasks('grunt-html-build');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('default', []);
};

Let’s test the html builder. Open up index.html and header.html and update them with the following code.

index.html

<html>
<head>
<title>Grunt test page</title>
<link href="./css/styles.css" rel="stylesheet" />
</head>
<body id="landing-page">
<h1>This is a title</h1>
<!-- build:section layout.header -->
<!-- /build -->
</body>
</html>

layouts/header.html

<h1>I'm the header partial!</h1>

If we run “grunt html” in the terminal, grunt will merge the header file into index.html and save it in our dev folder. Open up /dev/index.html to make sure that the code from our header template was included.

Putting everything together

Now, we will connect the tasks we just added to another two modules that go hand in hand, watch and browserSync. Watch’s job will be to check for changes in our source files and run the appropriate task. browserSync will run a local server with automatic reloading. Let’s install the modules now.

npm install grunt-browser-sync --save-dev
npm install grunt-contrib-watch --save-dev

Add the code for the modules to Gruntfile.js

grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');

We can now define a “watch” task (that will use grunt-contrib-watch), to watch out html and scss files. There’s two subtasks — html will check if any of the html files change and if they do will run the html builder task, and css will do the same for scss files.

watch: {
html: {
files: ['./src/**/*.html'],
tasks: ['htmlbuild']
},
css: {
files: 'src/scss/**/*.scss',
tasks: ['sass'],
},
},

With this, any changes to our scss & html files in /src/ will be automatically rendered into the dev folder. You can make sure it works by running “grunt watch” in the terminal and editing any of the html or scss files in src. Grunt will helpfully let you know that files have changed.

There’s one last thing to tie everything together. We’ll use browsersync to start a local server and load our files from dev there. Any updates to the files will be automatically added to the open browser window. Let’s add the browsersync task to Gruntfile.js.

browserSync: {
dev: {
bsFiles: {
src: [
'dev/css/*.css',
'dev/js/*.js',
'dev/*.html'
]
},
options: {
watchTask: true,
server: './dev'
}
}
}

With the task added, we also need to tell grunt that we want both the browserSync & watch tasks running together.

grunt.registerTask('default', [
'browserSync',
'watch'
]);

We’ll be using these two tasks a lot, so we added them as the default action —we can now just type “grunt” on the terminal to run the watcher and browsersync at the same time.

Gruntfile.js should look like this now.

module.exports = function(grunt) {grunt.initConfig({sass: {
dist: {
files: {
"dev/css/styles.css" : "src/scss/styles.scss"
}
}
},
htmlbuild: {
dist: {
src: './src/index.html',
dest: './dev/',
options: {
beautify: true,
relative: true,
basePath: false,
sections: {
layout: {
header: './src/templates/header.html'
}
},
}
}
},
watch: {
html: {
files: ['./src/**/*.html'],
tasks: ['htmlbuild']
},
css: {
files: 'src/scss/**/*.scss',
tasks: ['sass'],
},
},
browserSync: {
dev: {
bsFiles: {
src: [
'dev/css/*.css',
'dev/js/*.js',
'dev/*.html'
]
},
options: {
watchTask: true,
server: './dev'
}
}
}
}); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks('grunt-html-build');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('default', [
'browserSync',
'watch'
]);
};

With the gruntfile updated, we are ready to run our server. Type “grunt” in the terminal. This will start a server, and load index.html in the default browser.

With this done we’ve covered our set of requirements: stylesheets, html templates and a local server that track changes and reloads the page without our interaction.

There’s more to Grunt that just what we did today, like modules to minify javascript or shrink image files, but this is a solid base for most front end projects.

--

--