Jekyll is fantastic, easy to use, and extensible. However, some Jekyll hosts such as GitHub Pages do not allow people to use custom plugins - and I want category and year pages. But rightly so. Allowing custom plugins would require hosts to allow users to run arbitrary Ruby code on their build servers and possibly create a mess. This problem is solvable, but it’s ultimately simpler to just ban them entirely.
This constrained environment forces you to get creative. On this blog I use the fantastic jekyll-compress-html template which minifies the very post you are reading. I have written by own template to automatically replace standard markdown or HTML images with lazily loaded ones. And finally, I have written a small (it’s only a hundred or so lines ;) ) Makefile to automatically, among other-things, generate year and category pages:
To use, simply create _templates/category.html and a _templates/year.html templates and run make cat year. The code assumes your posts start with the date and they are stored in the default _posts/. When run #####CATEGORY##### and #####YEAR##### will be replaced with the templated value.
Intersection Observer is a relatively new API with decent support that can have a huge impact on performance. It has many uses and can trigger all sorts of code but this article is simply looking into performance. With it, image lazy loading can be quickly and easily added to any site including static Jekyll sites.
To start, define a variable to store the Interaction Observer. For simpler deployment, the code below avoids using modern JavaScript features such as let and arrow functions.
varobserver
Secondly, a function to load a given image. Here, a temporary image is created to load the image and if successful the source of the actual image is replaced.
But, the code above can only lazy-load images with very specific markup. This is where this nasty piece of Liquid code comes in. Liquid is fundamentally a very limited language with no direct way to initialise arrays, weird syntax, and no regular expressions. So, instead of using regular expressions, we can instead create a nasty piece of splitting code which works just well enough for the job.
The HTML Jekyll generates from Markdown is simple and regular enough for the following code to work. I would not expect it to work for more complicated HTML. But it’s worth a shot!
{%- assign excerpt = content | split: '<img src="' -%}
{%- for e in excerpt -%}
{%- if forloop.first == true -%}
{{ e }}
{%- else -%}
{%- if e contains '" alt="' -%}
{%- assign f = e | split: '" alt="' -%}
{%- assign url = f | first -%}
{%- assign g = f | shift | join: '" alt="' | split: '"' -%}
{%- assign alt = g | first -%}
{%- assign rest = g | shift | join: '"' -%}
<noscript><img src="{{ url }}" alt="{{ alt }}" /></noscript><img class="script-required" src="#" data-lazy-src="{{ url }}" alt="{{ alt }}"{{ rest }}
{%- else -%}
{%- assign f = e | split: '"' -%}
{%- assign url = f | first -%}
{%- assign rest = f | shift | join: '"' -%}
<noscript><img src="{{ url }}" /></noscript><img class="script-required" src="#" data-lazy-src="{{ url }}"{{ rest }}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
Now I recommend styling the unloaded images with width and height. If known ahead of time it can be set explicitly. Failing that, I recommend setting a generic default using CSS.
img{min-width:100px;min-height:100px;}
And finally with this in place, my site often enjoys a perfect score in Google Chrome Inspector Audit. It cleanly beats google.com which has a top score of 91 and even beats motherfuckingwebsite.com in every category but performance where it draws at 100.
After months of planningprocrastination, I have finally created a blog for this site of mine. I have used Jekyll site builder and Liquid templates to adapt this theme and add a blog. Hosting is provided by GitHub pages and I’ve bought a cheap .uk domain name.
London Fireworks 2018 LIVE - New Years Eve Fireworks: 2017 / 2018 - BBC One
In the coming days, weeks, whenever I will get around to adding new pages and backfilling old. But now with the technology in place, creating new pages is as simple as typing out markdown in Sublime Text, committing and refreshing the page. You can even subscribe to updates via RSS! Hope to see you soon!