Welcome to Jekyll!

October 4th, 2015 by Felix Schneider

Über die Beweggründe, einen Static-Site-Generator zu schreiben.

You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.

So begann meine Spielerei mit Jekyll. Es hat sich durch seine Verwendung auf GitHub durchaus einen Ruf eingeholt. Also, so dachte ich mir, spiele ich mal damit herum.

die Installation

Nach etwas Tippen und Scrollen durch die Suchseiten erschien es mir, als wäre die Installation via Ruby Gems die bei weitem einfachste Methode. Es hätte mich nicht gestört, für etwas mehr Aufwand ohne dem Ruby-Paketmanager auszukommen. Doch die Mehrinvestition schien unverhältnismäßig. Das störte mich schon mal, doch ich schaffte eine unkomplizierte Installation in ein Verzeichnis.

Nachdem ich auf einen anderen Rechner wechselte, merkte ich das erste Problem. Manche Bibliotheken waren architekturabhängig und schon spießte sich Jekyll. Schweren Herzens legte ich in einem anderen Unterordner eine Installation für die zweite Architektur an.

die Dateistruktur

Mit einem funktionierendem Jekyll im Nacken begann ich nun, mir eine Website aufzubauen. Flexibel war Jekyll jedenfalls, doch es erschien mir nicht so flexibel, wie ich es gern gehabt hätte. Es war stark als Blogging-System orientiert. Posts wurden allesamt in einem Verzeichnis abgelegt und so konnte ich dazugehörige Bilder oder andere Medien nicht seperieren. Es reichte jedoch, um meine ersten Wünsche zu realisieren. Schließlich hatte ich kaum Inhalte zu verwalten.

Dennoch spießte es mich ein wenig, dass ich nicht totale Freiheit über die Namen von Dateien in meinem Ordner hatte. Es gab einige Ordnernamen, die von Jekyll für bestimmte Zwecke bestimmt waren (z.B. _drafts, _includes, _layouts, _posts oder _data). Ich sah keinen Grund, Inhalte nicht an dem Ort in der Ordnerstruktur unterzubringen, an dem sie letztlich auch verbleiben würden. So kann der Gestalter beim Schreiben auch sicher auf andere Posts verweisen und ein Permalink-Generator-Subsystem wird überflüssig.

Meiner Ansicht nach sollten solche Daten außerhalb des Seiten-Verzeichnisses liegen, immerhin sind es mehr oder weniger Metadaten.

die verwendete Technologie

die Template-Engine

Liquid, wie sie hieß, tat ihr übriges. Die Syntax war recht ähnlich zu der von Jinja2, allerdings fand ich die Dokumentation teilweise unklar oder schwammig. Es irritierte mich jedoch, dass auch Posts von Liquid überfahren wurden. So konnte man in diesen zwar zusätzlich Funktionen realisieren, aber die Trennung zwischen Inhalt und Gerüst der Seite wurde ungenauer.

das Frontmatter

Die Idee, Metadaten in einer bestimmten Auszeichnungssprache am Anfangs des Textes anzugeben, gefiehl mir. Ich hielt es für sauber implementiert, wenngleich ich YAML nicht sonderlich lieb gewinnen konnte.

Bei der Implementierung meines eigenen Static-Site-Generators fiel mir auf, wie sehr mir in Jekyll wirkliche Vererbung von Variablen fehlen würde. Die von dem Tool gebotene Möglichkeit, in der website-weiten Konfiguration bestimmte Variablen für bestimmte Pfade anzugeben erscheint mir unsauber. Bei größeren Seiten kann sich da dann eine lange und unübersichtliche Liste zusammensammeln. Aus meiner Sicht wünschenswert wäre ein Konfigurationsdatei-Standardname, welcher, falls vorhanden, Variablen für das jeweilige Verzeichnis und dessen Unterverzeichnisse setzen kann.

Pagination

Als ich die Jekyll-Pagination kennen gelernt habe, war sie - wie man so schön sagt - "a pain in the ass". In der globalen _config.yml musste man sie konfigurieren. Das Ganze funktionierte, wenn ich mich recht erinnere, als Plugin.

Das wollte ich bei meiner Implementierung besser machen. Pagination sollte, so dachte ich, im Template spezifiziert werden. Und siehe da, der Aufwand erwies sich als eher gering. Im Nachhinein, und ohne den Quelltext des Tools gesehen zu haben, verstehe ich nur schwer, warum sie es von Anfang an so ungeschickt und gepfuscht eingebaut haben.

Changed-Only Build

Bei jedem Durchlauf wurde, wenn ich mich recht erinnere, das gesamte Ausgabeverzeichnis zuerst geleert und dann mit den Inhalten befüllt. Bei großen Seiten, so dachte ich mir, kann das Rendern der Seiten durchaus ein gutes Weilchen dauern. Ich suchte ein wenig auf Google. Siehe da, das Problem war bereits 2013 erkannt worden. Wie es im Hauptzweig nun aussieht, ist mir nicht klar. In der Dokumentation wird jedenfalls bisher weiter davor gewarnt, dass das Zielverzeichnis geleert wird. Es besteht lediglich die Option, einige Dateien in eine Ignore-Liste einzutragen.

Auch darauf habe ich bei meiner Implementierung Wert gelegt, vor allem, weil der Einbau eine kleine Angelegenheit war und sich bereits auszahlt, bevor ich viele Seiten habe. Warum Jekyll zu unfähig ist, einfach die Werte der letzten Änderung zu vergleichen, ist mir ein Rätsel.

die Alternativen

Bevor ich einen eigenen Static-Site-Generator schrieb, habe ich mich zuerst nach anderen umgesehen. Ich wollte nicht groß an den Templates umschreiben und außerdem Jinja2 lernen, also hatte ich schon einmal eine Präferenz für die Template-Engine. Jekyll fand ich nicht so schlecht, dass ich alles hätte aufgeben wollen. Python hätte ich als Programmiersprache durchaus akzeptiert, aber ich war nicht gewillt, mich durch all die verschiedenen Möglichkeiten durchzuackern.

Dann fand ich ein Modul in reinem Lua für Jinja2, und weitere in reinem Lua für JSON und Markdown-Parsing. Alle drei taugten für Lua 5.3 und somit war die Sache besiegelt.

Conclusio

Einige grundsätzliche Entscheidungen von Jekyll gefallen mir, und diese habe ich übernommen. Doch das Programm ist mir mittlerweile zu groß, um noch verwendet zu werden. deschneme.lua verwendet ebenfalls Frontmatters, allerdings in JSON geschrieben. Es frisst ebenfalls Markdown und die Syntax von Jinja2 ist nicht grob anders als jene von Liquid. Es kann ebenfalls Listen von Posts, es kann Kategorien, es kann sie sortieren. Plugins unterstützt es auch, lokal wie global, und Pagination ebenso. Um zu funktionieren, braucht es zwei kompilierte Lua-Module und zwei in Lua geschriebene Module. Dann kommt es mit 750 Zeilen Code aus.

Wer den Umstieg wagen möchte, dem sei die Dokumentation unter oben stehendem Link empfohlen. Und er oder sie möge gewarnt sein - die Fehlermeldungen der Template-Engine sind tückisch und erfordern Erfahrung im Umgang mit dem Tool.

Apropos: in den 750 Zeilen ist kein Webserver eingebaut. Aushilfe schafft zum Beispiel der Busybox Webserver oder auch darkhttpd. Im Falle des Busybox-Modells kann es sein, dass man für zusätzliche Dateiendungen wie SVG Mime-Typen in eine Config schreiben muss.