Automate hexo blogging tasks with Grunt

In my never-ending journey to find the optimal blogging platform, I wandered into the hexo camp. Among its many attributes is speed. Compared to Octopress, site generation is very fast. However, deployment has been tricky. Since I host my blogs from an Amazon S3 bucket, I tried to use the aws deployer commonly used with hexo; but I could never get it to install properly on OS X 10.11. So I wrote my own deployer that essentially just runs an AppleScript that handles the synchronization task. It is very slow. So I’m always on the lookout for faster deployment schemes. It looks like a Grunt-based system is the ticket.

Starting point for hexo automation

Chitrang Shah wrote a series of articles on setting up a blog using hexo, Amazon S3 and Grunt. His piece on automating deployment with Grunt was the starting point that I needed. His solution relies on the grunt-s3 plugin which unfortunately is no longer supported and doesn’t work with current versions of Grunt. But the concept is sound.

First more about Grunt:

About Grunt

As the Grunt page says, it’s a JavaScript task runner, meant for automating repetitive tasks like testing, deploying, etc. It installs easily:

npm install -g grunt-cli

The above will install grunt globally on the local machine. To use Grunt to automate your blogging tasks, you need to install the grunt shell plugin in the top level of your blog’s directory.

npm install grunt-shell --save-dev

Install Grunt plugins for sitemap and robots.txt

Install two additional plugins grunt-sitemap and grunt-robots-txt.

npm install grunt-sitemap --save-dev
npm install grunt-robots-txt --save-dev

Install Grunt plugin for S3 deployment

Here is where this solution diverges from Chitrang Shah’s. Instead of grunt-s3, I’m using grunt-aws.

npm install --save-dev grunt-aws

To use this plugin, you’ll have to modify Shah’s Gruntfile.js. Create the Gruntfile.js at the root level of your blog’s local directory. This file specifies the actions that are available from the command line.

module.exports = function(grunt){
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		aws: grunt.file.readJSON('grunt-aws.json'),
        // additional Configuration
    });
    // load and register tasks
};

Loading the npm tasks is straightfoward:

//Load NPM tasks
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-robots-txt')
grunt.loadNpmTasks('grunt-sitemap');
grunt.loadNpmTasks('grunt-aws');

Then we just need to string the tasks together in logical sequence.

//Grunt tasks
grunt.registerTask('default', ['shell:clean', 'shell:generate', 'sitemap:dev',
'robotstxt:dev', 'shell:server']);
//grunt.registerTask('staging', ['shell:clean','shell:generate','sitemap:staging',
'robotstxt:staging', 's3:staging']);
grunt.registerTask('deploy', ['shell:clean', 'shell:generate', 'sitemap:production', 'robotstxt:production',
's3']);

I’m ambivalent about staging for a small blog; so I’ve left it out. YMMV.

Use a separate file that is not checked into version control for your AWS credentials. My grunt-aws.json looks like this:

{
    "accessIdProduction" : "...",
    "accessKeyProduction" : "...",
    "bucketProduction" : "..."
}

The complete Gruntfile.js for this blog is available as a gist.

Finally, to use our new blog automation to clean, generate, and serve the blog locally, it’s just grunt. To clean, generate and deploy, it’s grunt deploy. This is a very straightforward way to automate your hexo blog and speedily deploy it to S3.