While building my personal blog http://www.cheeyeo.uk, I made the decision to explore other blogging frameworks outwith of the traditional MVC framework structure.
After reading an article about Jekyllrb on the Thoughtworks Technology Radar, I made the decision to learn more about Jekyllrb by building this site using it.
One of the features lacking in using a static site generator is asset management. In Rails we have the Asset pipeline which carries out the compilation and minifcation process. Whilst using Jekyll I decided to roll my own using Grunt.js.
Step 1: Structuring the assets
I would need to structure my assets in such a way that ONLY the required files are included into the final build. In Jekyllrb, any directory can be included into the final _site folder if it is not excluded from _config.yml.
Rather than having to manually update the config file, I learnt that any folder which starts with an underscore will be automatically excluded from the _site folder. I created a _assets folder which will hold all my sass and js files. A _tmp directory is also created as a temporary holding area which will be made clear below.
Step 2: Making the gruntfile
The main grunt tasks I would require to handle the assets for this site includes the following:
- Compiling the javascript and sass files
- Minifying / compressing the assets for production
There are already many grunt plugins available, such as grunt-contrib-concat, grunt-contrib-uglify and grunt-contrib-sass.
Below is a snippet of my Gruntfile.js for handling js and sass files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
concat: {
options: {
separator: ';',
},
dist: {
src: ['_assets/js/*.js','!_assets/js/modernizr.*'],
dest: '_tmp/site.js'
}
},
uglify: {
my_target: {
files: {
'_tmp/site.min.js': ['_tmp/site.js']
}
}
},
sass: {
global: {
options: {
style: "compressed"
},
files: {
"_tmp/global.css": "_assets/scss/global.scss"
}
}
},
...
});
The concat task essentially joins the required js files together from _assets/js into _tmp/site.js which the uglify task picks up to generate the compressed js file into _tmp/site.min.js. Likewise, the sass task joins and compresses the css into _tmp/global.css
Step 3: Adding the assets to the build process
The trickiest task is to combine the Grunt.js workflow into the Jekyllrb structure.
I came across the jekyll-minibundle which both minifies and generates asset fingerprinting. Since the above Grunt tasks already does minification I am only using the asset fingerprinting.
This would allow me to cache my assets using Rack::StaticCache in my config.ru file. ( More on deploying your jekyllrb site in a separate article !)
Within the partials, I made the following declarations:
ministamp is a command from jekyll-minibundle. It generates a fingerprint of _tmp/global.css and moves into _site/assets/global.css once the site is being built.
If _tmp/global.css were to change, the fingerprint will change which means you get automatic asset cache expiry, just like the asset pipeline!
Conclusion
Jekyllrb is a very versatile system and there are many variations one can use to handle assets. Coupled with Grunt.js which also has a healthy ecosystem of plugins and tasks ready to use, handling assets in static websites need not be difficult.