Automate and livereload a jekyll site with less using grunt
I’ll be the first to admit it, my “workflow” is/was really ancient, my professional work is to 99% done in Visual Studio which has made me a bit spoiled since it handles almost anything you want it to do. Work that I do for fun on the other hand is mostly written with sublime text. This site for instance is built with jekyll and I use LESS as a preprocessor for its stylesheets.
My old workflow for developing/writing posts for this site was pretty much non-existant. I used Winless for compilling LESS and it has the occasional hiccups where it wouldn’t listen to updates in imported files and recompile my main LESS file. I also ran jekyll build
manually from a bash prompt. The Winless issue meant that I sometimes had to compile jekyll, realize that the LESS file wasn’t compiled and thus not updated in the new build so I had to manually compile LESS and then build jekyll again, a time consuming and headache inducing experience I can assure you.
I’ve been interested in GruntJS for a while now but I didn’t realize that I could use it to solve my issue before reading Chris Coyiers article, I also feared that it would be hard since it runs on node. Turns out that setting up grunt on windows was a breeze and that creating a grunt file for this project wasn’t to hard, mainly because a lot of people has written about parts of what I tried to achieve. Chris’s article covered most of it but I also had to find some posts about jekyll and grunt, and then merge this information.
I will try to make an abridged version of the information that I’ve compiled, referring back to the original content but also write my conclusions in case the original posts disappears.
Setting it up
Chris Coyier writes about the basics of setting up grunt, all you have to do is go to http://nodejs.org/ and click the install button. You then create a file called “package.json” in your sites root folder with the following:
And then run npm install
in your console of choice (I use the git bash) while “standing” in your site root folder e.g, cd c:\myfolder
in cmd or cd /c/myfolder
in the git bash to install your dependencies. UPDATE: I’ve had this step fail for me with the error Error: ENOENT, stat c:\users\username\AppData\Roaming\npm
, I solved this by copying the npm
file from my node js installation, in my case this was C:\Program Files\nodejs
into my roaming folder.
We must now install the Grunt CLI, this is what makes the grunt command that we will run later work. We do this by executing npm install -g grunt-cli
in the console. UPDATE: My “copying npm file” fix seems to be causing issues with this, remove the npm file again since this command wants to create a directory called npm.
Now it’s time to write our gruntfile that will compile less and build jekyll, it should of course do this without us having to press reload in our browser.
We will begin with this small gruntfile that compiles our less on the fly, we don’t have to install livereload on our machines since this is built into grunt-contrib-watch
, but we still have to install a browser plugin
What this does is that it listens to changes in any LESS file in my /assets/styles folder. It compiles and minifies rosengren.less
to rosengren.css
by running the less:development
task from the watch:less
task when it detects an update. It also notifies livereload in any browser and injects the new CSS without refreshing the page.
Now is a good time to execute grunt
in the console and make sure that everything is working so far. the console should answer with `Running “watch” task, Waiting. Make a change in one of your less files and the console window will come to life and tell you what it’s doing.
I found a post by Thanasis Polychronakis That describes how to get grunt to build jekyll through a shell task. And also added that we should have an additional task that copies compiled less directly to our _site folder without having to build jekyll since it takes a lot of time.
We do this by adding these tasks directly into the grunt.initConfig
parameter object, they should be added right next to the less
and watch
tasks.
We should also add 'copy:css'
into the watch:less
tasks array. and a secondary watch task that should be added next to the watch:less
task
We also have to tell grunt to load additional tasks for our config file to make sense.
The copy
task copies the rosengren.css
file into our _site folder, this will be run when our watch:less
detects a change since we added the task into the tasks array and it will be included in the livereload.
The new watch:jekyll
task will listen to any change in files that should trigger a jekyll build, it will then trigger the shell:jekyll
task and a livereload after it has finished.
The new tasks that we’re loading should be added within the main function of the file, next to the previously loaded tasks.
Finally
Well there you have it, a jekyll site that builds when files are updated and compiles and injects LESS when it detects any change in a LESS file.
The grunt file for this site as of writing can be found here