Seite 1 von 1

Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 11.12.2024 06:44:32
von paedubucher
Hugo

Hinter diesem Türchen verbirgt sich Hugo: ein mächtiger und äusserst performanter Generator für statische Webseiten. Der Name dürfte einerseits an die Programmiersprache Go erinnern, in der er implementiert ist. (Go macht es einfach, Aufgaben zu parallelisieren, was wohl ein wichtiger Faktor für die ausserordentlich hohe Performance von Hugo sein dürfte.) Das “Hu” (wie “huge”) dürfte eine Anspielung darauf sein, das man mit Hugo riesige Seiten in nützlicher Frist generieren kann.

Themes: vorgefertigte und eigene

Zum Einstieg in Hugo wird oft empfohlen ein vorgefertigtes Theme zu wählen. Das ist für die meisten Seiten sicherlich ein guter Rat. So habe ich positive Erfahrungen mit dem äusserst mächtigen Relearn-Theme gemacht, das u.a. LaTeX-Formeln mit MathJax, Diagramme mit Mermaid und eine clientseitige JavaScript-Suche out of the box mitbringt. Ich brauche das für meine Unterrichtsmaterialien, siehe etwa die Webseite für mein Cloud-Modul.

Privat habe ich zwei Webseiten am Laufen: zum einen meine Hauptwebseite paedubucher.ch, die auf einem selber gebauten Hugo-Theme basiert. Neulich habe ich mir an einem Abend einen neuen Blog namens Read, Think, Write zusammengehackt. Hier kommt ebenfalls ein eigenes Theme zum Einsatz, aber ein äusserst minimalistisches. Die Webseite ist ein one pager im wahrsten Sinne des Wortes, dank HTML-Minifizierung aber trotzdem sehr schlank. (Die .woff-Schrift Bitter, die ich mit ausliefere, ist zugegebenermassen ein Luxus.) Wie man so etwas baut, möchte ich in diesem Türchen zeigen.

Liebes Tagebuch

Analog zu meinem Blog Read, Think, Write möchte ich zeigen, wie man mit Hugo eine kleine Tagebuch-Webseite erstellt. Von einer frischen Installation von Debian 12 “Bookworm” ausgehend soll zunächst einmal Hugo installiert werden:

Code: Alles auswählen

$ sudo apt install -y hugo
Im Gegensatz zu den generierten Webseiten ist Hugo leider alles andere als schlank, was auf die statisch gebauten Binärdateien von Go zurückzuführen ist. Der Bloat bleibt aber lokal; der Webseitenbesucher bekommt Minimalismus ausgeliefert: ein akzeptabler Kompromiss!

Nun soll die Tagebuchseite initialisiert werden:

Code: Alles auswählen

$ hugo new site tagebuch
Dadurch wird folgender Verzeichnisbaum generiert:

Code: Alles auswählen

$ tree tagebuch
tagebuch/
├── archetypes
│   └── default.md
├── assets
├── config.toml
├── content
├── data
├── layouts
├── public
├── static
└── themes
Diese Verzeichniseinträge haben folgende Bedeutung:
  • archetypes: Dieses Verzeichnis enthält Vorlagen für neue Seiten. Das Template default.md enthält einen YAML-Header für den Titel und das Tagesdatum. Das werden wir gleich in Aktion sehen.
  • assets: Hier kommen Dateien hinein, die von Hugo verarbeitet (z.B. “minifiziert”) werden, wie z.B. CSS- oder JavaScript-Quellcodedateien.
  • config.toml: Hierbei handelt es sich um die Konfigurationsdatei für die ganze Webseite, die auf der Hugo-Webseite sehr detailliert dokumentiert ist. Diese liegt standardmässig im TOML-Format vor. Wichtige Einstellungen sind die baseURL der Webseite, die ich auf https://tagebuch.paedubucher.ch ändere; der languageCode, den ich gut schweizerisch auf de-ch umstelle; und der Titel, den ich auf Mein Tagebuch ändere. Weitere Ergänzungen finden sich unten.
  • content ist das Verzeichnis, welche die Seiteninhalte als Markdown-Dateien enthält. Dieses Verzeichnis werden wir gleich mit Inhalt befüllen.
  • data enthält Dateien, die in den Hugo-Templates angesprochen werden können. Ich selber habe das noch nie verwendet, doch die Dokumentation gibt Auskunft darüber.
  • layouts enthält eigene Templates um die Seite zu generieren. Es kommen die selbst für Go-Programmierer etwas gewöhnungsbedürftigen Go-Templates zum Einsatz.
  • public ist das Verzeichnis, in welches das generierte HTML mit den Zusatzdateien (CSS, JavaScript) landet. Dieses Verzeichnis kann man von einem Webserver ausliefern lassen. Ich selber schliesse es aus meinem Git-Repository aus; es gibt aber Leute, die auch das generierte HTML in die Versionskontrolle aufnehmen.
  • static ist für statische Dateien wie Bilder oder Schriftarten gedacht, die 1:1 (ohne weiteren Verarbeitungsschritt durch Hugo) ausgeliefert werden.
  • themes kann mehrere Themes enthalten, die dann über die Konfiguration aktiviert werden. Wir werden in diesem Beispiel keine Themes verwenden.
So sieht meine Konfiguration config.toml aus:

Code: Alles auswählen

baseURL = 'https://tagebuch.paedubucher.ch'
languageCode = 'de-ch'
title = 'Mein Tagebuch'

[minify]
minifyOutput = true

[params]
author.name = "Patrick Bucher"
meta.description = "Mein Tagebuch"
meta.keywords = "Tagebuch, Blog, Persönliches"
Im Abschnitt minify wird angegeben, dass die HTML-Ausgabe verkleinert werden soll. Dadurch werden überflüssige Leerzeichen und sonstige Syntaxelemente aus dem HTML-Code entfernt, die für eine korrekte Darstellung im Browser unnötig sind. Das HTML bleibt aber standardkonform.

Metadaten sind im Abschnitt params definiert. Dies sind Angaben für die Meta-Tags author, description und keywords, die später im Template zum Einsatz kommen sollen.

Das Tagebuch wäre nun von technischer Seite her aufgesetzt. Nun soll das Layout erstellt werden.

Layout mit Go-Templates

Beim Layout handelt es sich um eine HTML-Datei, in welcher der dynamische Teil als Go-Template eingestreut wird. Die Datei wird unter layouts/index.html abgelegt:

Code: Alles auswählen

<!doctype html>
<html lang="de-ch">
  <head>
    <meta charset="UTF-8" />
    <meta name="author" content="{{ .Site.Params.Author.Name }}" />
    <meta name="description" content="{{ .Site.Params.Meta.Description  }}" />
    <meta name="keywords" content="{{ .Site.Params.Meta.Keywords }}" />
    {{ $css := resources.Get "style.css" | minify }}
    <link rel="stylesheet" type="text/css" href="{{ $css.RelPermalink }}" />
    <title>{{ .Site.Title }}</title>
  </head>
  <body>
    <header>
      <h1>{{ .Site.Title }}</h1>
    </header>
    <main>
      {{ range $_, $page := .Pages }}
      <article>
        <h2>{{ $page.Params.Title }}</h2>
        <p><em>{{ time.Format "02.01.2006" $page.Params.Date }}</em></p>
        {{ $page.Content }}
        <hr />
      </article>
      {{ end }}
    </main>
    <footer>
      <p>© {{ .Site.Lastmod.Format "2006" }} by {{ .Site.Params.Author.Name }}.</p>
    </footer>
  </body>
</html>
Der Header enthält die üblichen Metadaten, welche über die .Site-Datenstruktur abgerufen werden können. Angaben wie Params.Meta.Keywords dürften anhand der Konfiguration in config.toml ziemlich einleuchtend sein.

Die CSS-Datei style.css wird zuerst “minifiziert” und dann per link-Tag eingebunden.

Der Seitentitel .Site.Title kommt sowohl für den title- als auch für den h1-Tag zum Einsatz.

Im Hauptbereich der Seite wird über die Inhaltsseiten (.Pages) iteriert. Die $page-Datenstruktur steht dann für eine einzelne Inhaltsseite, deren Inhalt als $page.Content ausgegeben werden kann. Das Markdown wurde in HTML gerendert. Die Datumsangabe wird typisch für Go formatiert: Man gibt einfach das gewünschte Format exemplarisch für den zweiten Januar 2006 an, das dann mit der Funktion time.Format anhand der Angabe $page.Params.Date dargestellt wird.

Zuunterst gibt es noch einen footer mit Copyright-Angaben. Auch hier kommt wieder eine Datumsformatierung anhand des gleichen Beispieldatums (Jahr 2006) zum Einsatz.

Eine minimalistische CSS-Datei soll unter assets/style.css zu liegen kommen:

Code: Alles auswählen

body {
    margin: 0 auto;
    max-width: 30em;
}

p {
    text-align: justify;
}
Dadurch wird die Seite auf eine Breite von 30 “ems” begrenzt und im Blocksatz ausgerichtet.

Inhalt

Nun geht es ans Erstellen des ersten Eintrags. Hierbei ist uns Hugo behilflich:

Code: Alles auswählen

$ hugo new content/hallo-welt.md
Dadurch wird eine neue Datei unter content/hallo-welt.md erzeugt, bei welcher title (anhand des Dateinamens) und date (anhand des aktuellen Zeitstempels) bereits vorausgefüllt sind. Den Header draft: true kann man testhalber gleich auf false umstellen, damit man die Seite zu Sehen bekommt. Die Seite wird mit etwas Inhalt im Markdown-Format befüllt:

Code: Alles auswählen

---
title: "Hallo Welt"
date: 2024-12-10T20:49:25+01:00
draft: false
---

Liebes Tagebuch. Es freut mich, mit dir bekannt zu werden. Ich möchte dich in Zukunft täglich pflegen und dich mit Inhalt füllen. Dank Hugo geht das sehr kombortabel und W3C-Standardkonform obendrein!
Und weil das so einfach ging, erstellen wir gleich noch den nächsten Eintrag:

Code: Alles auswählen

$ hugo new content/dfde-adventskalender.md
Der Inhalt des zweiten Beitrags:

Code: Alles auswählen

---
title: "DFDE-Adventskalender"
date: 2024-12-10T20:54:18+01:00
draft: false
---

Liebes Tagebuch. Ich sollte wirklich an meinem Zeitmanagement arbeiten. Es ist Dienstagabend kurz vor 21 Uhr, und ich bin nun seit ungefähr einer Stunde daran, meinen Türchen für morgen zu schreiben. Damit hätte ich schon [im Oktober](https://debianforum.de/forum/viewtopic.php?t=190688) anfangen sollen! Aber letztes Jahr ging ja auch alles gut.
Mit zwei Einträgen lohnt es sich nun, das Tagebuch einmal zu rendern. Hierzu bietet Hugo einen integrierten Webserver, der sich folgendermassen starten lässt:

Code: Alles auswählen

$ hugo server
Die Webseite kann nun unter localhost:1313 aufgerufen werden. Auf die Anzeige verzichte ich an dieser Stelle, ihr sollt ja auch etwas zu tun haben.

Eine Seite, die unter der angegebenen Domain (siehe baseURL in config.toml) ausgeliefert werden kann, wird folgendermassen ins public-Verzeichnis generiert:

Code: Alles auswählen

$ hugo
Die Generierung ist rasend schnell. Dies ist bei einer Seite mit so wenig Inhalt und einfachem Template nicht weiter verwunderlich, bei grösseren Seiten wartet man aber auch selten eine Sekunde lang auf die Ausgabe.

Nun?

Was meint ihr zu Hugo? Kommt das für euch in Frage? Ist die Template-Sprache einigermassen verständlich? Habt ihr Lust bekommen, einen kleinen Blog zu starten?

Nachtrag: Offenbar macht die Forensoftware völlig unnötig einen Link aus tagebuch.paedubucher.ch. Die Seite existiert nicht, und ich habe die URL mit tt-Tags umgeben. Warum die als Hyperlink angezeigt wird, ist mir schleierhaft. :?

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 11.12.2024 13:04:48
von dasebastian
Vielen Dank für den Hugo, der kommt wie gerufen!

Ich werde nächstes Jahr wahrscheinlich anfangen müssen einen kleinen Webauftritt für unseren Hof zu bauen. Hugo scheint dafür perfekt zu sein und ist somit in meine Notizen dazu gewandert. Spitze sowas. :THX:

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 11.12.2024 13:20:45
von uname
Vielen Dank für diesen schönen Beitrag. Vor allen im kommerziellen Umfeld werden Webseiten statisch generiert, da es die Webserver bei Millionen von Aufrufen extrem entlastet. Ein Produkt im kommerzielen Umfeld ist OpenText™ Web Site Management früher RedDot von https://www.opentext.com.

Ich für meinen Fall schreibe meine Webseiten noch vollständig in HTML, CSS, JavaScript und PHP und dabei evtl. mit W3.CSS. Aber das funktioniert nur bei kleinen Webseiten. Wenn man statische Webseiten auf Basis dynamischer Inhalte benötigt, benötigt man Software wie Hugo, die dynamische Inhalte in statische Webseiten umbauen. Eine Art Zwischenlösung sind FlatFile CMS-Systeme, wobei deren Inhalte zwar keine Datenbank benötigen, jedoch dynamisch zur Laufzeit und damit mit mehr Aufwand beim Aufruf erzeugt werden.

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 11.12.2024 22:01:32
von mn77de
Auf dieses Türchen habe ich mich besonders gefreut! Vielen Dank dafür!!! :hail:

Einfache statische Seiten habe ich bisher auch direkt mit php/html/css erstellt.
Ich vermute, dass sich dies zukünftig ändern wird und mir da Hugo unter die Arme greift. :wink: 8)

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 12.12.2024 06:38:57
von paedubucher
mn77de hat geschrieben: ↑ zum Beitrag ↑
11.12.2024 22:01:32
Auf dieses Türchen habe ich mich besonders gefreut! Vielen Dank dafür!!! :hail:

Einfache statische Seiten habe ich bisher auch direkt mit php/html/css erstellt.
Ich vermute, dass sich dies zukünftig ändern wird und mir da Hugo unter die Arme greift. :wink: 8)
Es freut mich, dass du mit dem Türchen etwas anfangen kannst!

Wenn du für deine Seiten PHP verwendet hast, war es ja schon nicht mehr statisch. :wink:

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 12.12.2024 07:20:15
von mn77de
paedubucher hat geschrieben: ↑ zum Beitrag ↑
12.12.2024 06:38:57
Wenn du für deine Seiten PHP verwendet hast, war es ja schon nicht mehr statisch. :wink:
Ja, jein, ... :lol:
Effektiv könnte ich PHP hier gut weglassen.

Spontan gefragt ... wie ist das bei Hugo mit dynamischen Elementen?
Hab' gesehen, dass mit Hugo sogar eine Volltextsuche möglich ist.

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 12.12.2024 08:36:11
von debianoli
Ich nutze Hugo für Webseiten, die wartungsfrei und sicher laufen sollen. Das Stopfen von Sicherheitslücken wie bei Wordpress fällt weg.

Hugo benötigt relativ wenig Einarbeitung, am Besten spielt man am Anfang mit den vielen fertigen Templates rum.

Re: Adventskalender 11. Dezember 2024 - Hugo

Verfasst: 12.12.2024 09:11:59
von paedubucher
debianoli hat geschrieben: ↑ zum Beitrag ↑
12.12.2024 08:36:11
Ich nutze Hugo für Webseiten, die wartungsfrei und sicher laufen sollen. Das Stopfen von Sicherheitslücken wie bei Wordpress fällt weg.
Das ist der Vorteil von statischen Webseiten. Ausserdem verursachen diese Seiten praktisch keine CPU-Last, da nur statische Dateien ausgegeben werden. Mein Webserver hat eine CPU und 512 MB Memory, worauf mehrere häufig besuchte Seiten laufen. Der Server ist trotzdem noch überdimensioniert.