07.05.2024 10:08
Jekyll - eine performante Alternative
Wer heute eine Webseite baut, kann zwischen vielen unterschiedlichen Vorgehen und Frameworks wählen. Die meisten davon sind sehr mit JavaScript überladen, oft unnötigerweise. Sehr oft verursachen diese Frameworks auch eine relativ hohe CPU-Last auf dem Server, weil sie beispielsweise in PHP geschrieben sind und gleich darauf ausgelegt alles zu können - einen Editor für Posts mitzuliefern, mehrbenutzerfähig zu sein, erweiterbar durch Plugins, etc. Solche Frameworks gehen auch immer mit einer Datenbank einher.
Diese Features sind gut, aber nicht unbedingt immer nötig. Vor allem stören sie, wenn man versucht auf sehr kleiner Hardware (ca. auf dem Niveau eines IoT Devices) eine Webseite zu betreiben. Das Ergebnis sind stark ruckelnde Seiten, welche die kleine Hardware nur unnötig ins Schwitzen bringen.
Eine Alternative bieten Frameworks an, welche statische Webseiten (ohne Datenbank) aus Markdown Dateien generieren - z.B. Jekyll.
Gerade persönliche Blogs lassen sich auf diese Art und Weise vortrefflich organisieren! Wenn man selbst der einzige schreibende Nutzer ist und auf einen Texteditor im Webbrowser verzichten kann (ganz ehrlich, es gibt bessere Programme um mit Text zu arbeiten) - dann braucht man keine schwere Datenbank, keinen meilenlangen PHP Code! Kleine, stromsparende Server werden mit den so erstellen statischen Webseiten auch locker fertig!
Aber, was tun, wenn man einen mehrsprachigen Blog, oder eine mehrsprachige Webseite betreiben will? Zumindestens bei Jekyll gibt es auf der Webseite keine Anleitung dazu.
Mehrere Sprachen - mehrere Probleme
Sucht man im Internet, findet man durchaus Anleitungen die genau dieses Problem angehen. Man sollte sich aber davor hüten, einfach die erstbeste Anleitung zu nehmen und ihr zu folgen. Es mag sein, dass anfangs alles gut geht, aber es kann leicht passieren, dass der Autor dieser Anleitung nicht die Kompatibilität seines Vorgehens mit allen Plugins (ein sehr wichtiges Element bei Jekyll!) gecheckt hat. So kann es passieren, dass man tagelang an einer Webseite arbeitet, scheinbar Fortschritte macht, aber dann vor eine Wand läuft die nur noch durch hässliche Hacks zu umgehen ist. Viel Erfolg beim nächsten Update, wenn alles wieder zusammenbricht…
Grundsätzliche Tipps
Will man eine Webseite mit Jekyll bauen, so sollte man vermeiden sich in die Neuerfindung des Fahrrads zu stürzen! Das gilt allgemein für jedes Softwareprojekt. Hier meine grundsätzlichen Tipps im Detail:
- Immer auf die offiziellen Ressourcen als erstes zurück greifen, nicht einfach drauflos suchen
- Auf GitHub gibt es viele Themes für Jekyll. Schaut euch vor allem die an, welche die meisten Sterne haben. Nehmt sie als Muster zur Erstellung eines eigenen Themes, oder verwendet diese direkt weiter
- Versucht so weit wie möglich nicht Funktionen von Jekyll zweck entfremdet zu benutzen. Collections sind z.B. nicht dazu da mehrsprachigen Inhalt anzuordnen
Was sind denn die offiziellen Ressourcen? Anlaufstelle Nr. 1 ist die Hauptseite des Projekts: Jekyll. Dort im Bereich Docs findet ihr schon eine sehr gute Anleitung und Erklärung für erste Schritte. Will man jedoch weiter gehen, und hat man etwas vor, was in dieser Anleitung nicht beschrieben ist, so ist ein Blick auf die Ressourcen angesagt. Vor allem empfehle ich die Liste der Jekyll Plugins.
Im weiteren Verlauf dieser Anleitung setze ich voraus, dass die offiziellen Ressourcen mitbenutzt werden. Das Jekyll-Team hat eine Anleitung schon geschrieben und es wäre falsch diese einfach zu kopieren, stattdessen habe ich ja oben darauf verlinkt.
Multisprachiger Blog
Wie baut man also genau einen multisprachigen Blog mit Jekyll? Hier sind die Plugins, die man m.M.n. zumindestens nehmen sollte:
- “jekyll-paginate-v2”
- “jekyll-polyglot”
- “jekyll-sitemap”
- “jekyll-seo-tag”
Diese sind im Gemfile einzutragen, so sieht es bei mir aus:
gem "jekyll-feed", "~> 0.12"
gem "jekyll-paginate-v2"
gem "jekyll-polyglot"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
Jekyll-feed ist dabei standardmäßig immer schon drin, wenn man eine neue Jekyll Webseite anlegt.
Es gibt mehrere Plugins die man GitHub unter “jekyll-polyglot” findet. Ich benutze untra/polyglot. Es hat viele Sterne, sieht aktiv aus und hat bei mir gut funktioniert.
Wenn man auf GitHub auf die Seite von diesem Plugin geht, kann man unter “Used By” sehen, wer alles in seinem Theme dieses Plugin verwendet. Kleiner Tipp: nehmt euch eines dieser Themes, oder nutzt es als Template ;-)
Datenstruktur
Die richtige Datenstruktur ist sehr wichtig, sonst kann einer der folgenden Fehler passieren:
- die Webseite sieht funktionsfähig aus nach einem
bundle exec jekyll serve
, sobald man aber in Produktion gehen will und den statischen Inhalt auf einen “normalen” Server (apache httpd, nginx, etc.) lädt sind einige der Links kaputt und führen zu einem 404-Error - Posts werden nicht als solche erkannt, oder tauchen in der falschen Kategorie auf
Unser Blog soll multisprachig werden. Außerdem brauchen wir mehrere Kategorien, wie z.B. einen Blog und ein Portfolio, möglicherweise einen separaten News-feed für Updates welche die Seite selbst betreffen.
- Jede Kategorie braucht ein eigenes Unterverzeichnis. Diese Ordner gehören ins Wurzelverzeichnis. Z.B.:
my-website blog photos portfolio
Gebt euren Kategorien sprechende Namen, sie werden später in jedem Post im Front Matter gesetzt und zur Pagination genutzt!
- Die Posts sind unter dem jeweiligen Unterverzeichnis anzulegen. Posts gehören bei Jekyll in einen Ordner der
_posts
heisst. So sieht es bei mir aus:my-website blog _posts photos _posts portfolio _posts
- Da die Seite mehrsprachig werden soll, gehören da noch Unterverzeichnise für die Sprachen rein:
my-website blog _posts de en uk photos _posts de en uk portfolio _posts de en uk
Die Seiten werden aus .md Dateien generiert. Den Pfad, unter dem die generierte .html Datei zugänglich wird, steuert man durch das Attribut
permalink
im “Front-Matter” der Seite, sowie durch diepermalink: ...
Einstellung in der_config.yml
.Jede Sprache braucht eine andere .md Datei, da im Front-Matter keine Variablen genutzt werden können, nur Klartext. Will man eine .md Datei für mehrere Sprachen nutzen, wird das “title” Attribut der generierten Seite immer gleich bleiben, sowie “description”, usw.
Ausschnitt aus der
_config.yml
(Konfiguration von Polyglot, beliebige Sprachen hier hinzufügen):- Legen wir eine
index.md
Datei an (Standardsprache für die Webseite ist Deutsch). Einfach im Wurzelverzeichnis anlegen. Hier ist das Front Matter:title: "Mehrsprachige Webseite!" lang: de permalink: / page_id: index link_title: "Start" description: "Ein Blog in mehreren Sprachen"
- Jetzt dasselbe für Englisch. Die Datei muss nun anders heissen, sonst wird ja die alte überschrieben. Z.B.
index.en.md
:title: "Multilang website!" lang: en permalink: / page_id: index link_title: "Home" description: "A blog with multiple languages"
Usw., für jede Sprache die noch benötigt wird
- Legen wir nun die .md Dateien für unsere Kategorien an, diese werden später die Posts für diese jeweilige Kategorie abbilden. Ich lege die Datei
blog.md
so an:title: Blog page_id: blog permalink: /blog categories: blog lang: de description: "Blog" pagination: enabled: true indexpage: blog category: blog
Hier wird es schon etwas komplizierter.
lang
zeigt weiterhin die Sprache des Inhalts an. Das wird vom Polyglot Plugin benutzt, um Links korrekt zu generieren (ca. nach dem Muster [lang]/[categories]/[permalink].html). Der Bereich pagination ist notwendig, damit man die Posts in dieser Kategorie nicht alle auf einer Seite anzeigt, sondern mit der Zeit auch ein Vor- und Zurückblättern ermöglicht. Hier ist es wichtig eine gesonderte indexpage zu definieren, sonst überschreiben sich die Kategorien gegenseitig, sobald Pagination greift. Category muss gesetzt sein, damit die Posts aus anderen Kategorien hier nicht auftauchen. Leider versteht pagination nicht das Attribut “lang”. Daher tauchen zunächst mal Posts in allen Sprachen hier auf. - In diesem Schritt erweitern wir das Front Matter von blog.md, damit nur die Posts auf Deutsch angezeigt werden:
title: Blog page_id: blog permalink: /blog categories: blog lang: de description: "Blog" pagination: enabled: true tag: de indexpage: blog category: blog
Ich weiss, ich habe weiter oben geschrieben, dass man Funktionen nicht zweck entfremden sollte. Ich fand aber keinen besseren Weg, als den “tag” im Post zu nutzen, und hier nach eben diesem “tag” zu filtern. Immerhin ist es nicht ganz falsch, die Sprache des Artikels kann auch durchaus als “tag” gesetzt werden. Jetzt werden unter blog.md nur die Posts angezeigt, welche:
- auf Deutsch sind (wo “tag: de” gesezt ist)
welche zur Kategorie Blog gehören (wo “categories: blog” gesetzt ist)
- Vermutlich habt ihr schon ein Theme ausgesucht, oder ihr macht ein eigenes. Unabhängig davon, müsst ihr in einer der Layout Dateien die Anzeige der Posts aktivieren. Angenommen ihr habt eine default.html als den Layout für alle Seiten. Dann muss dort an der Stelle, wo die Posts aufgelistet werden sollen, zumindestens folgendes hin:
Wie man das paginate-v2 Plugin konfiguriert, ist am besten hier beschrieben.
- Jetzt müssen noch die .md Datein für alle anderen Seiten angelegt werden, je eine pro Sprache, genau wie oben beschrieben.