Eleventy Templates mit Daten anreichern

Einer der Gründe, weshalb ich ein großer Fan von Eleventy bin, ist die Möglichkeit, Templates mit beliebigen Daten anzureichern und daraus Seiten zu generieren. Früher habe ich Seiten normalerweise mit Wordpress erstellt, da ich es kannte und damit meine Probleme lösen konnte. Als ich dann anfing, einen Podcast zu veröffentlichen, brachte mich Christian (@derschepp) auf die Idee, mit einem static-site generator meine Webseite zu veröffentlichen, da es hier ja möglich sei aus externen Daten, wie einem RSS-Feed, die Webseite zu erzeugen.

Ich war neugierig und fing an, mit Eleventy herumzuspielen und 5 Jahre später, ist es noch immer mein favorisiertes Tool, wenn es darum geht, Webseiten zu erstellen.

In diesem Artikel gebe ich einen Einblick in den Umgang mit Daten in Eleventy, wo man diese definiert, wie man hier mit dynamischen Daten arbeiten kann und wie wir, bis zu einem gewissen Grad, dynamische Templates erstellen können.

Der _data Ordner

Ursprung für alle Daten, ist der _data Ordner: hier kann man .json und .js Dateien ablegen, die Daten bereitstellen.

Auf dieser Webseite habe ich in meinem _data Ordner beispielsweise eine metadata.json, die u. a. folgende Inhalte hat:

{
"social": [
{ "href": "https://twitter.com/danielzenzes", "title": "Twitter" },
{ "href": "https://chaos.social/web/@danielzenzes", "title": "Mastodon" },
{ "href": "https://github.com/dzenzes", "title": "GitHub" }
]
}

In jedem meiner templates kann ich auf diese Informationen zugreifen und daraus meine Seite generieren. Die oben genannten Daten nutze ich im Footer, um die Links zu erzeugen.

{%- for link in metadata.social %}
<a href="{{ link.href | url }}">{{ link.title }}</a>
{%- endfor %}

Dynamische Daten erzeugen und einbinden

Nun gibt es aber auch immer wieder Daten, die aus einer anderen Quelle stammen und aus denen man Seiten generieren möchte. Bei mir war das ursprünglich immer der Wunsch, den RSS-Feed, den mein Podcast Anbieter bereitstellt, zu konsumieren und daraus eine Seite zu erzeugen. Hierzu lege ich im _data Verzeichnis eine Datei episodes.js an und nutze folgenden Code (hier etwas vereinfacht)

const Parser = require('rss-parser');

module.exports = async function () {
let parser = new Parser();
return await parser.parseURL('https://herrmies.podigee.io/feed/mp3');
};

Mithilfe von rss-parser lade ich den RSS-Feed und wandle ihn in json um. Nun kann ich diese Dateien in meinem Template verwenden und könnte so unter anderem eine Liste der Folgen mit einem kleinen Audioplayer erzeugen:

{% for item in episodes.items %}
<article>
<h2>{{item.title}}</h2>

<audio class="audio" controls="controls" preload="auto">
<source type="audio/mpeg" src="{{item.enclosure.url}}" />
</audio>
</article>
{% endfor %}

"Dynamische" Templates

Etwas, das ich auf der Seite von David East gelernt habe, sind dynamische Templates. Man kann nämlich auch aus Templates heraus relativ komfortabel Inhalte laden.

Zunächst benötigen wir hierfür einen asynchronen Shortcode. Shortcodes sind eine Möglichkeit, die jeweils verwendete Template-Engine, um eigene Befehle zu erweitern.

Sagen wir mal, wir möchten Code aus unserem GitHub Repository dynamisch in unseren Templates einbinden. Hierzu könnten wir in diesen folgenden Code ergänzen:

<pre>
<code>
{% github path="user/repo/branch/file.js" %}
</code>
</pre>

Der Shortcode muss dann nur noch in der Eleventy Konfiguration (.eleventy,js) angelegt werden:

import { fetch } from 'node-fetch';

async function fetchCode(githubPath) {
const response = await fetch(githubUrl(`https://raw.githubusercontent.com/${githubPath}`));
const code = await response.text();
return { githubPath, code };
}

module.exports = (eleventyConfig) => {
// ...
eleventyConfig.addNunjucksAsyncShortcode('github', async function ({ path }) {
const { code } = await fetchCode(path);
return code;
});
// ...
};

Natürlich sind diese Templates nur zur Build-Time "dynamisch" da am Ende eine statische Seite erzeugt wird. Wenn man hier noch Daten laden möchte kommt man an JavaScript nicht vorbei.

Kennt ihr noch andere Anwendungsfälle für Daten in Eleventy oder habt ihr einen kreativen Use-Case? Schreibt mir gerne auf Mastodon oder Twitter.