Grunt and AWS S3: how to streamline your deployment process

Grunt and AWS S3: how to streamline your deployment process

Here's a scenario  lot of us developers find ourselves in: you built your amazing static site. And when it came to deciding on your build tool you chose Grunt,  because it simplifies the build process. Everybody else uses it, and there's a reason: it works wonders. Everything is set: jit-grunt - read our jit-grunt guide here - usemin and purifycss are configured and are  working. You tested and retested everything with browserSync and your site is ready to go. And you want to upload your static site to an S3 bucket on AWS. It's hip. It allows you and your team to not worry about a webserver and focus only on the front-end. So what do you do? You go to the AWS Management Console and upload your dist folder to S3 manually every time. Right? Wrong!

The Problem

As you already know the reason you chose Grunt is to streamline your build process. Mundane tasks are completed in milliseconds, and you and your team focus all your time on the development - and testing. So why keep that last part - uploading to S3 - a manual process? That approach takes way too much time out of your process. Alternatively you might be already using the AWS Command Line Interface. This approach is slightly faster, as you don't have to log in to the AWS site, and you keep everything into the realm of your terminal. It's faster. But it remains a manual process. Do you have to do upload your dist folder to S3 manually? No!

The Solution

Use a Grunt plugin, grunt-aws-s3, to do all the heavy lifting for you. It's a simple plugin that provides you with a brand new Grunt task that logs into AWS with your credentials, takes the files you want - in our case the dist folder - and uploads them to the right bucket. Here is how to install it via npm:

npm i grunt-aws-s3 --save-dev

Congratulations: you have a brand new Grunt task available! The new task is called aws_s3. At this point you are going to need your AWS-provided Access Key Id and Secret Access Key. Create a a file called aws-keys.json and paste this in:

{
    "AWSAccessKeyId": "YOUR ACCESS KEY ID",
    "AWSSecretKey": "YOUR SECRET ACCESS KEY"
}

Note: remember to EXCLUDE this file from your commits. Only you should have access to your credentials. We're going to reference that brand new file in a few steps. And of course we are going to need  the name of the S3 bucket you're going to upload to. Your Gruntfile.js should look a lot like this:

grunt.initConfig({

    ...
    aws: grunt.file.readJSON( 'aws-keys.json' ),
  
    aws_s3: {
        options: {
            accessKeyId: '<%= aws.AWSAccessKeyId %>',
            secretAccessKey: '<%= aws.AWSSecretKey %>'
        },
        dist: {
            options: {
                bucket: 'YOUR BUCKET NAME'
            }
        }
    }

    ...
});

Are you all set up with that configuration? Just add the files you want to upload in the exact same format you use for your Grunt tasks. For example, at Blu Frame we like to use the Files Array format:

files: [
    {
        expand: true,
        cwd: 'dist/',
        src: [ '**' ],
        dest: '/'
    }
]

Don't worry if you don't know where that bit of code goes. We're going to show the whole configuration at the end of this guide. Finally register a new Grunt task to deploy your files. It's just for convenience, because let's face it, aws_s3 is not an intuitive word to remember. In this example we called our task deploy:

grunt.registerTask( 'deploy', 'aws_s3:dist' );

All done! Every time you develop a new feature, build your site using grunt build and you are happy that your code is production ready, just type in:

grunt deploy

Your dist folder is now automatically uploaded to your S3 bucket. As promised, here is what your Gruntfile.js is going to look like after all the steps we just went through:

grunt.initConfig({

    ...
    aws: grunt.file.readJSON( 'aws-keys.json' ),
    
    aws_s3: {
        options: {
            accessKeyId: '<%= aws.AWSAccessKeyId %>',
            secretAccessKey: '<%= aws.AWSSecretKey %>'
        },
        dist: {
            options: {
                bucket: 'YOUR BUCKET NAME'
            },
            files: [
                {
                    expand: true,
                    cwd: 'dist/',
                    src: [ '**' ],
                    dest: '/'
                }
            ]
        }
    }

    ...
});

grunt.registerTask( 'deploy', 'aws_s3:dist' );

And what did we learn?

The whole reason you use Grunt is to streamline your build process, and if you're choosing to host your entire site in an S3 bucket, your deployment process has to be just as streamlined. Fa too many developers are taking a manual approach to this step. It doesn't make sense, and is a waste of cumulative hours - sometimes not days. You can streamline your build _and _deployment process easily by using grunt-aws-s3. All you need to do is install it via npm, add a simple configuration and - for conveniency - register a deploy task.

Edoardo L'Astorina

Edoardo L'Astorina

Edoardo L'Astorina has 15 years of experience in software development. Edoardo has had a major role in the new Transport for London site and led the development of the new Royal Opera House site. Edoardo has developed sites and apps for Intuit, Stint, JPC, The Crocodile and Miura Edoardo started Blu Frame to help companies develop sites that stand out, load fast and are easy for users to access Edoardo is passionate about risotto, Terrence Malick movies, Oasis songs and rowing