Monsterlijk snelle blogs met Jekyll

Op dit blog heb je al een aantal artikelen voorbij zien komen over WordPress, het content management systeem dat bijna alles kan. Mijn artikel over WordPress, van augustus vorig jaar, ging voornamelijk over hoe je een WordPress-blog zo snel mogelijk kon krijgen. Voor wie dat artikel nog niet gelezen heeft: je site snel maken komt neer op het zorgen dat er weinig gedaan hoeft te worden, zowel aan de server-kant als aan de client-kant, voornamelijk door slim gebruik te maken van caching.

Een snelle website maken met Jekyll: een supersnelle website met Jekyll

Helemaal aan het einde van stap 2 van dat artikel noemde ik kort de Super Cache-plug-in voor WordPress. SuperCache is een plug-in die – elke keer als je een wijziging maakt – je blog omzet in een mapje met statische HTML-bestanden. Op die manier hoeft WordPress niet geladen worden om de site op te dienen.

Waarom Jekyll?

Met Super Cache gebruik je WordPress eigenlijk als een programma om dat mapje te genereren. Op zich erg handig natuurlijk, met name als je veel waarde hecht aan de vele features van WordPress: de makkelijke webinterface, vele plug-ins, en meer van dat alles. Maar een WordPress-installatie moet wel ingesteld en bijgehouden worden. (Zowel het instellen als het bijhouden is bijna geen werk, met dank aan Installatron en de update-functies van WordPress, maar toch.) Als je er over nadenkt gebruik je nu relatief veel ‘bewegende’ onderdelen voor een relatief eenvoudige taak. Anders gezegd: een groot, complex CMS gebruiken om een handjevol HTML-bestandjes te genereren is een beetje als een spijkertje inslaan met een graafmachine.

Nee, wat je zou willen, als programmeur of iets technischere webbouwer, is een eenvoudig systeem. Liefst iets dat net zo’n beetje in zit tussen een ‘echt’ CMS als WordPress en ‘gewoon met de hand’ alle HTML-bestanden van je site in elkaar zetten. Dat laatste is veel werk, vooral omdat de meeste pagina’s van je site vaak op elkaar zullen lijken. Na de twintigste keer je header en footer gekopiëerd te hebben heb je daar vaak wel genoeg van.

Een snelle website maken met Jekyll: logo Jekyll

Een systeem om dit probleem aan te pakken heet een static site generator. Het zet een beschrijving van de inhoud en lay-out van een website om in volledige HTML-bestanden, klaar om geserveerd te worden. Dit artikel is een korte inleiding voor mijn favoriete generator: Jekyll.

Een goed begin…

Jekyll is een tool om websites in elkaar te zetten, met een nadruk op sites die regelmatig nieuwe artikelen hebben: weblogs dus. Daar houdt de vergelijking met WordPress wel ongeveer op. Waar WordPress een vriendelijke interface heeft die ook voor beginners makkelijk te begrijpen is, is Jekyll ‘gewoon’ een commandoregel-applicatie. Een tool voor programmeurs, dus.

Hoe je Jekyll precies installeert is afhankelijk van je besturingssysteem. Windows-gebruikers hebben pech: Jekyll wordt officiëel niet ondersteund op Windows. Het is werkend te krijgen, maar met name de installatie vergt wat creatief configuratiewerk. Veel makkelijker is het op een Mac- of Linuxmachine. De officiële installatie-instructies zijn wat summier, maar de installatie zelf is eenvoudig genoeg. De pagina heeft ook en een link naar informatie over de Windows-variant, voor wie dat toch wil proberen.

Installatie geslaagd? Mooi. De rest van dit artikel is eigenlijk in twee stukken opgedeeld: eerst een stoomcursus blogs bouwen met Jekyll, gevolgd door drie trucs om het resultaat nóg sneller te krijgen dan het al is. De stoomcursus is erg kort. Wie meer wil weten kan opnieuw goed bij de officiële documentatie terecht.

Om maar meteen te beginnen: de eerste stap in elke Jekyll-site is het opzetten van de correcte mappenstructuur. Dit klinkt ingewikkelder dan het is. Het komt neer op het jekyll new-commando uitvoeren:

wn ~/Jekyll> jekyll new monsterblog
New jekyll site installed in /home/wn/Jekyll/monsterblog.
wn ~/Jekyll> cd monsterblog/
wn ~/Jek/monsterblog> jekyll serve
Configuration file: /home/wn/Jekyll/monsterblog/_config.yml
            Source: /home/wn/Jekyll/monsterblog
       Destination: /home/wn/Jekyll/monsterblog/_site
      Generating... done.
    Server address: http://0.0.0.0:4000
  Server running... press ctrl-c to stop.

Het tweede commando, jekyll serve, zorgt ervoor dat je het resultaat meteen kunt zien, in dit geval via ‘http://localhost:4000’. Als het goed is krijg je, als je nu naar dat adres gaat, de standaard Jekyll-site te zien. Niet verkeerd, maar ook niet erg… nou ja… monsterlijk.

Een snelle website maken met Jekyll: nieuwe website met Jekyll

…en het halve werk

Het jekyll new-commando heeft voor ons een configuratiebestand klaargezet, _config.yml. Dit kunnen we nu aanpassen. Vervang de inhoud bijvoorbeeld door het volgende:

name: Monsterblog  # ...of de naam van jouw blog, natuurlijk.
permalink: pretty  # Artikel-links zonder .html er achter.

Om het blog echt monsterlijk te maken moeten de lay-outbestanden en stijlbestanden ook aangepast worden. We hebben enge letters nodig, en bloedspetters uiteraard. Daarnaast moeten er natuurlijk monsterlijke artikelen geschreven worden.

De artikelen (posts) van een Jekyll-site gaan in de map _posts. De namen van de bestanden in die map hebben een vaste indeling: eerst de datum, dan de titel, dan .markdown. Dat is niet toevallig. Jekyll gebruikt deze informatie om een correcte URL te bouwen voor elke artikel.

Voor elke post en pagina kijkt Jekyll of er YAML front-matter in het bestand zit. Front-matter is het blok aan het begin van het bestand, omringd door de driedubbele strepen. In dat blok geef je aan wat de titel, datum en layout van het stuk is, en alles wat je verder nog wilt vermelden over de post of pagina in kwestie. Die informatie is vervolgens beschikbaar in de layouts.

---
layout: post
title:  Meeting Mr. Hyde
date:   2014-01-15 09:00:00
---
And at last his patience was rewarded (...)

Wat is dan zo’n lay-out? Lay-outs zijn vergelijkbaar met wat in CMS’en wel templates of themes genoemd worden. Ze beschrijven hoe je pagina’s er uit gaan zien, en bevatten bijvoorbeeld de header, footer en navigatie van je site. Anders gezegd, alle onderdelen die op meerdere pagina’s te zien zijn gaan in een lay-out. Alle lay-out-bestanden gaan in de map _layouts.

Jekyll ondersteunt voor de lay-outs de Liquid template language, een soort kleine programmeertaal die het mogelijk maakt om redelijk complexe lay-outs in elkaar te zetten, mocht je dat willen. Een volledige behandeling van Liquid zou wat te lang uitvallen voor dit artikel, maar hier is een voorproefje:

<div id="home">
  <ul class="posts">
    {% for post in site.posts %}
      <li><span>{{ post.date | date_to_string }}</span> &raquo; <a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
</div>

Kom je er niet uit? Shopify, de bedenkers van Liquid, hebben handige lijsten van de beschikbare tags (zoals for hierboven), en Jekyll heeft een aantal handige filters toegevoegd (zoals date_to_string).

Alles wat Jekyll niet ‘snapt’ – plaatjes, CSS-bestanden, HTML-bestanden zonder front-matter – wordt rechtstreeks van de invoermap naar de uitvoermap gekopiëerd. Daar is dus niks speciaals voor nodig.

De voorbeeldsite die we in de volgende stappen gaan gebruiken is het speciaal voor dit artikel in de ere geroepen Monsterblog. De Jekyll-broncode van de uiteindelijke site is te zien via de GitHub-repository. Als je wilt kun je met de knop ‘Download ZIP’ in één keer de hele site downloaden. (Als je je eigen Jekyll-site wilt beginnen is het misschien leerzamer om gewoon te beginnen met jekyll new.) De site zelf staat op monsterblog.twnc.org.

Een snelle website maken met Jekyll: een Monsterblog maken!

Zo! Je hebt posts, pagina’s en lay-outs. Je hebt waarschijnlijk zelfs nog een paar plaatjes om je blog wat op te leuken. Draai voor de zekerheid nog een keertje jekyll build en upload de inhoud van het mapje _site naar je website, en je website is klaar. Er is geen database om in te stellen, geen plug-ins te installeren. Alle slimmigheden zijn immers al gedaan.

Je gloednieuwe site zou al vrij snel moeten zijn, maar ‘vrij snel’ is natuurlijk niet voldoende. Wij willen ‘monsterlijk snel’. Daarom: drie tips om een snelle site nog sneller te maken.

Who you gonna call? Eeuwig cachen en cache busting

Net als bij onze razendsnelle WordPress-site is een groot gedeelte van het geheime recept het gebruik van caching. Nu we Jekyll gebruiken kunnen we daar zelfs nog wat verder in gaan dan we de vorige keer gegaan zijn. We kunnen browsers gaan vertellen afbeeldingen en stijlbestanden voor eeuwig te bewaren. (Voor eeuwig? Ja, voor eeuwig – oftewel zo lang de browser van je bezoeker zin heeft er aan vast te houden.)

Anders dan bij WordPress is het nu volledig aan jezelf om caching correct in te stellen. In ons geval gaan we dat doen door een .htaccess-bestand te plaatsen in de mapjes waar afbeeldingen en stijlen in zitten. Zo’n .htaccess-bestand zou er ongeveer zo uit kunnen zien:

Header set Cache-Control "max-age=31449600, public"
Header unset ETag
FileETag None
Header unset Last-Modified

Eeuwig cachen is prima – totdat er iets op je site veranderd moet worden. Een kleurtje anders, bijvoorbeeld, of een plaatje dat vervangen moet worden. Met eeuwig cachen hoeft de browser niet aan de server te vragen of de onderdelen die ‘ie heeft verzameld nog wel ‘vers’ zijn. Resultaat? Alle bezoekers die al eerder zijn geweest zullen ‘netjes’ de verouderde pagina te zien krijgen. Met de oude kleur dus, bijvoorbeeld.

Eigenlijk zouden we een manier willen hebben om de browser te vertellen dat een afbeelding of stylesheet gewijzigd is – en dan liefst zonder dat de browser daar zelf om moet vragen. Technieken om dit te bewerkstelligen worden meestal samengevat onder de noemer cache invalidation. Een van de eenvoudigste manieren om dit aan te pakken heet cache busting – en dat is precies wat we gaan doen. (Cache invalidation kan erg complex zijn. Een gezegde gaat ongeveer zo: “Er zijn eigenlijk maar twee moeilijke dingen in de computerwetenschappen: cache invalidation, namen verzinnen voor dingen, en dat soort vervelende programmeerfouten waarbij je er nét 1 naast zit.”)

Cache busting is, zoals gezegd, erg simpel. De truc is om een stukje achter de bestandsnaam achter te plakken dat elke keer verandert als je het bestand aanpast:

styles.css?201401101642

Apache negeert het gedeelte achter het vraagteken, maar browsers denken elke keer als de datum verandert – terecht! – dat er een hele nieuwe styles.css te downloaden valt.

Zo’n datum-string met de hand bijhouden is vervelend. Veel handiger is om de tijd te gebruiken waarop de site voor het laatst gegenereerd is, bijvoorbeeld met dit stukje Liquid-code:

styles.css?{{ site.time | date: "%Y%m%d%H%M" }}

Als je de voorbeeldsite bekijkt zul je zien dat deze snipper op een aantal plekken voorbijkomt.

Kleinere plaatjes met Optipng

Als je de eerste truc correct geïmplementeerd hebt weet je nu zeker dat je stijlbestanden en afbeeldingen nooit vaker geladen worden dan nodig. Maar wat als dat niet genoeg is? Wat als je, net als ik, echt nog die laatste milliseconden er wilt afschaven?

In het eerdere artikel kwam het al even naar voren: een groot gedeelte van de hoeveelheid data die voor een pagina gedownload moet worden bestaat vaak uit plaatjes. Een foto zegt meer dan duizend woorden, maar is ook snel duizend (of een miljoen) keer zo groot. Stap 3 van dat artikel had een aantal tips voor eenvoudige programma’s om plaatjes wat te verkleinen. Voor onze Jekyll-site kunnen we daar nog een tool aan toevoegen: optipng. Optipng is speciaal geschreven voor PNG-afbeeldingen en gaat vaak nét nog wat verder dan de meeste compressie-tools.

Het programma is, net als Jekyll, een commandoregel-applicatie. Gebruik gaat ongeveer zo:

optipng bestand.png

Optipng zal reageren met ofwel een percentage dat het van het bestand heeft weten af te snoepen, of het bericht dat het bestand niet kleiner kan (‘file is already optimized’).

Back to the future: agressief vooruitladen

Tegen de tijd dat je hier aangekomen bent – met je volledig statische, cache-busted, minified blog – is de snelheid van je site bij wijze van spreken slechts nog beperkt door de wetten van de natuurkunde. Een packet met het verzoek om een pagina op te halen doet er, afhankelijk van je internetprovider, je locatie, je webhostingprovider en een grote stapel andere factoren, wel zo’n 20 milliseconden over om het Internet te doorkruisen. Twintig tergende milliseconden! Wie aan de andere kant van een oceaan woont mag daar nog eens 100 à 200 ms bij optellen, simpelweg omdat Hengelo dan zo ver weg is.

Het liefst zou je een stukje in de toekomst willen kijken, en je site al op de pc van je bezoeker zetten, voordat hij of zij op het idee komt een bezoek te brengen. Niemand kan natuurlijk in de toekomst kijken, maar truc 3 van deze drieluik komt een aardig eind in de buurt.

Het idee is om al te beginnen met het laden van een pagina als er met de muis over een link gegaan wordt, in plaats van te wachten totdat er daadwerkelijk ook geklikt wordt. Dat laden kan onopvallend in de achtergrond gebeuren. Het praktisch nut van dit alles is dat de volgende pagina nu al (deels) gearriveerd is als de beslissing om te klikken wordt gemaakt – en dan kan er meteen gesprongen worden. Een laadtijd van 0 ms. Veel sneller dan dat gaat ‘m niet worden.

Een handig stukje JavaScript-code dat dat preloaden (voorladen in krom Nederlands) voor je kan doen is InstantClick. Installeren gaat door net voor je </body>-tag het instantclick.js-bestandje aan te roepen:

<script src="/js/instantclick.js" data-no-instant></script>
<script>InstantClick.init();</script>

(Deze techniek klinkt misschien een beetje als voodoo, maar het is vergelijkbaar met wat Google Chrome doet met zoekresultaten. Chrome zoekt voor de bovenste paar resultaten alvast in de achtergrond naar de bijbehorende IP-adressen, zodat ze al in een cache zitten op het moment dat de gebruiker eindelijk besloten heeft op de bovenste link te klikken. Pienter.)

Fin

Wie een blog maakt met Jekyll krijgt zelf het gereedschap in handen. Het is, helemaal als je een beetje kunt programmeren, een immens flexibel systeem. Anders dan bij zware CMS-systemen is er géén overhead op het moment dat je site geladen wordt, en krijg je alle ruimte de allerlaatste milliseconden van je laadtijd af te schrapen. Succes!

P.S. Wil je op de hoogte blijven van alle artikelen, tips en trucs die verschijnen op ons blog? Dat kan! Rechts bovenin via RSS, e-mail, het liken van onze Facebook-pagina of het volgen op Twitter.