logo-bs logo-dxn logo-odl

Frontend automation with Grunt, Sass + BrowserSync.

The front-end team at JH are always looking at ways to improve development workflow. We love checking out new tools and techniques and will often integrate the most useful ones into our stack.

Of all the tools we evaluate, the ones most likely to make it into our daily workflow usually fall into the same category: Task Automation. That is, taking a particular action that was once done manually many times per day and delegating it to a machine.

Whether it’s compiling SASS files into CSS when a file changes, linting and combining Javascript files, generating sprite-sheets, keeping multiple browsers/devices in sync with CSS changes or any other similar task – the goal is always to remove any mundane/repetitive tasks from the workday and focus on what you do best – building and designing.

Why automate?

It’s all about focusing our efforts on the areas in which we excel – human beings can be extremely good at certain things whilst also being embarrassingly bad/inefficient at others. No-one wants to waste their time, so automation is all about letting the machines handle the stuff we don’t do so well, which in turn gives us more time to focus on our strengths.

We’re good at…

Using creativity to solve problems. The ability to think creatively and innovate is by far our greatest asset. This is where we should be spending the vast majority of our time and effort. We cannot automate this – and we’d never want to either.

We’re NOT good at…

Any repetitive task that requires the same action, over and over again. – In the front-end developer world this could be any of the following:

  1. Hitting reload in the browser whenever you make a CSS change.
  2. Filling out the same form on multiple devices to test styling.
  3. Returning to the command line to run SASS compile or something similar.
  4. Creating sprite-sheets in Photoshop manually.
  5. Combining many Javascript files into one.
  6. Plus many more…

The above is by no-means an exhaustive list, but it does highlight some of the most common time-wasting tasks that can occur in any front-end developers workflow.

Time to automate

In this tutorial we’ll look at automating a few of those repetitive tasks using Grunt and a few open-source plugins. We’ll look at a couple of examples that will:

  • Allow us to write SCSS files and compile them automatically into CSS…
  • Have those changes appear instantly in multiple browsers.

But before that, there are a couple of tools we need to install.

Node and Grunt installation

Grunt is a command-line tool for managing task automation. There are already countless blog posts and tutorials explaining what it does and how to install it, so we’ll just briefly cover the installation process and then dive in to actually using it.

Install NodeJS

First of all, you’ll need NodeJS which is a one-click install via the link.

Install grunt-cli

Once you have Node installed, you’ll need to run the following command to install the grunt-cli globally. This gives you the command-line interface for grunt (that’s the cli part) and allows you to use the tool anywhere on your computer.

npm install -g grunt-cli

If you’re on a mac/linux and that command fails, you may need to run it with *sudo*

sudo npm install -g grunt-cli

Project specific Package.json and Gruntfile.js

Now that you have NodeJS and Grunt installed GLOBALLY, you need to add these two files into the root of your directory.

Package.json

Think of this file as the configuration for your project. It will contain a list of all the tools that we install – (known as devDependencies) and a few other optional pieces of information, such as project name, version etc.

This file is something that you would check-in to version control so that anyone who works on the project at a later date can have the exact same tooling setup that you’ve been using.

To create the file, in the root of your project run:

npm init

This command will present you with a bunch of questions, but feel free to just hit enter until you reach the end. It will create the file package.json

// package.json - created with 'npm-init'
{
  "name": "my-awesome-project",
  "version": "0.0.0",
  "description": "My Awesome Project",
  "main": "index.js",
  "directories": {
    "doc": "doc"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "BSD"
}

Notice how the name field does not contain any spaces or special characters – this is a requirement so just make sure whatever you put here follows that rule.

Gruntfile.js

The tools that we’ll be using require a little bit of configuration – they need to know where to find our files and what to do with them. This is where the Gruntfile comes in. We’ll use this file to list our tasks and define the order in which they should run.

Create the file in the same directory as the package.json we created earlier (which should also be your project root).

// Gruntfile.js
module.exports = function(grunt) {
    // Task configuration will go here
};

Installing local Grunt

We installed `grunt-cli` globally before, but each one of our projects needs to contain the actual grunt package (which allows different versions across projects). Back on the command line, just run:

npm install grunt --save-dev

The --save-dev part at the end will also add it as a project dependency (in the package.json). As mentioned previously, if you want other people on your team to work with the exact same tools, you should always add this flag when installing anything new.

Recap

That’s all the setup needed. We can now move on to actually using some of these tools – but first, just to recap, let’s look at what we’ve already done.

  1. Installed Node.js
  2. Installed grunt-cli globally using npm install -g grunt-cli
  3. Moved into a project and created a package.json file using npm init
  4. Manually created a Gruntfile.js in the same directory.
  5. Installed Grunt locally to our project

With all the setup complete, we can now move onto the first example of task automation…

Compiling SASS/SCSS into CSS on file-change

To accomplish this, we’ll need two grunt plugins – grunt-contrib-watch and grunt-contrib-sass (note: you’ll also need SASS installed on your machine as Grunt will simply be triggering it. Follow the link for installation instructions).

// Install the plugins
npm install grunt-contrib-watch grunt-contrib-sass --save-dev

Now you have the plugins installed, you need to tell Grunt where to find your files. Open up the Gruntfile.js we created and enter the following (ensuring that the directories match your project setup).


module.exports = function (grunt) {
  grunt.initConfig({
    // Watch task config
    watch: {
      sass: {
        files: "app/scss/*.scss",
        tasks: ['sass']
      }
    },
    // SASS task config
    sass: {
        dev: {
            files: {
                // destination         // source file
                "app/css/styles.css" : "app/scss/styles.scss"
            }
        }
    },
  });

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

The config above assumes a directory structure like this:

index.html
/app/css
/app/scss

If you set everything up correctly, you can now simply run:

grunt watch

and every time a SCSS file is changed, the SASS task will run and compile into CSS.

Note: you can also run the SASS task on it’s own and it will just run once.

// compile scss files once & exit
grunt sass

Ok, now that we have SASS generating CSS for us automatically, let’s take it one step further.

Automatically reload CSS in the browser

Wouldn’t it be cool if we could automatically insert the newly created CSS into the web page we’re working on, without having to hit reload in multiple browsers? We thought so and that’s why we developed a tool called BrowserSync. You can read more about what BrowserSync does here.

BrowserSync can watch the CSS files that are compiled from the task above and automatically reload them into all connected browsers when they change. As usual, we can install it with NPM.

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

Once installed, we just need to let BrowserSync know a few things about our project:

  • Where is your compiled CSS file?

Because we are using SASS to compile into CSS, we just need to tell BrowserSync where the final CSS file will be.

  • Are you using .html files, or do you already have a local server?

BrowserSync can launch a mini-server for you if you’re just using HTML/CSS/JS files – it will just need to know which is your base directory. Or alternatively, if you’re running a local server with PHP or anything similar, you’ll need to use the proxy mode. BrowserSync will wrap your existing with a proxy URL to view your site. Examples of both are provided below.

// inside Gruntfile.js
// Using the BrowserSync Server for your static .html files.
browserSync: {
  default_options: {
    bsFiles: {
      src: [
        "css/*.css",
        "*.html"
      ]
    },
    options: {
      watchTask: true,
      server: {
        baseDir: "./"
      }
    }
  }
}
// inside Gruntfile.js
// Using the BrowserSync Proxy for your existing website url.
browserSync: {
  default_options: {
    bsFiles: {
      src: [
        "css/*.css",
        "*.html"
      ]
    },
    options: {
      watchTask: true,
      proxy: "yourvhost.dev"
    }
  }
}

Putting it together.

With the BrowserSync config from above, we can start turning these separate tasks into a complete workflow. We’ll do this by registering a default task with Grunt. Here we can specify which tasks should run when grunt is typed into the command line with no other arguments.

// register a default task.
grunt.registerTask('default', ['browserSync', 'watch']);

That’s all the config needed – you can now return to the command line and simply run:

grunt

With that single command, all of the following things will happen:

  1. BrowserSync will be started.
  2. Your default browser will be opened (on a special URL that can access by any device on the wifi network).
  3. Your SCSS files will be watched and compiled when they change.
  4. The resulting CSS will be auto-injected into all browsers/devices that you have connected.
  5. As a bonus, because we chose BrowserSync for the CSS injecting, we also get the other features it has, such as: click, scroll and form synchronisation.

Take a look at the full Gruntfile.js and package.json files so see it all together.

So what have we achieved here?

In this short introduction to Grunt, the command-line and front-end tooling in general – we have put together a really efficient workflow that removes as many of the tedious/repetitive tasks from your work day as possible. You can have a browser window open next to your editor and see the changes that you make to SCSS files appear live in the browser – all without you ever having to hit reload! When you see this happening across multiple monitors, phones and tablets all at the same time, you might think it’s magic – but you’ll definitely be thinking ‘I can’t live without this now’.

Resources

Looks like there are no related posts

Start the conversation

Whether it’s a new site or an existing one, Jamie’s ready to respond to you on
jamie@wearejh.com or +44(0)115 933 8784