DevCore.net

CMS vs. SSG: Wann welches Setup sinnvoll ist

Ein fairer Vergleich ist wichtig: Weder ein klassisches CMS noch ein SSG ist pauschal besser. Entscheidend sind dein Team, der Workflow, die Änderungsfrequenz und die technischen Anforderungen.

Kriterium Monolithisches CMS (z. B. WordPress / TYPO3) Modernes SSG-Setup (z. B. 11ty / Hugo + Cloudflare Pages)
Performance & Speed 🟡 Mittelmäßig bis Gut
Dynamischer Serveraufruf verzögert die Ladezeit. Erfordert aufwendiges Caching für Spitzenwerte.
🟢 Exzellent
Reine HTML-Dateien liegen direkt auf dem CDN. Extrem schnelle und weltweit konstante Ladezeiten.
Sicherheit (Angriffsfläche) 🔴 Höheres Risiko
Live-Datenbanken, PHP-Laufzeiten und unzählige Plugins bieten permanente Angriffsflächen für Hacker.
🟢 Minimales Risiko
Keine Datenbank, kein PHP auf dem Server. Es gibt für Angreifer schlicht kein direktes System zum Hacken.
Wartung & Updates 🔴 Hoher Aufwand
Regelmäßige, kritische Updates für Core, Plugins und Themes sind Pflicht, um Sicherheitslücken zu schließen.
🟢 Minimaler Aufwand
Einmal generiert, läuft die fertige HTML-Seite theoretisch jahrelang wartungsfrei und ohne Sicherheitsrisiko.
Hosting & Fixkosten 🟡 Mittel
Benötigt klassischen Webspace oder Server mit PHP/Datenbank. Skalierung bei viel Traffic kostet extra.
🟢 Sehr niedrig bis Kostenlos
Static-Hosting via Cloudflare, Netlify und Co. ist in der Regel permanent gratis oder extrem günstig.
Inhaltspflege (Redaktion) 🟢 Sehr einfach
Komfortable visuelle Editoren (WYSIWYG) und Medienbibliotheken. Perfekt für nicht-technische Teams.
🔴 Komplexer
Erfordert standardmäßig Markdown-Dateien oder Git. Ohne technisches Verständnis kaum pflegbar.
Vorschau-Funktion 🟢 Nahtlos im Backend
Inhalte können vor der Veröffentlichung direkt per Knopfdruck im Backend-Design geprüft werden.
🟢 Isolierte Preview-URLs
Generiert automatische Test-Links pro Ticket/Änderung. Perfekt für strukturierte Freigabeprozesse.
Live-Veröffentlichung 🟢 Sofort live
Nach dem Klick auf "Speichern" ist die Änderung in derselben Sekunde für alle Besucher weltweit sichtbar.
🟢 Vollautomatisiert
Läuft modern und fehlerfrei über eine CI/CD-Pipeline. Der Build-Prozess dauert meist nur wenige Sekunden.
Dynamische Features 🟢 Inklusive
Logins, Formulare, Suchen oder Shop-Systeme lassen sich nativ oder per Plugin sofort out-of-the-box nutzen.
🔴 Aufwendig
Benötigt für jedes dynamische Feature externe Drittanbieter, APIs, JavaScript-Frameworks oder Serverless Functions.

Fazit

  • Wann das CMS gewinnt: Ein monolithisches CMS ist oft die bessere Wahl, wenn nicht-technische Teams Inhalte pflegen, eine sofortige Direktbearbeitung gewünscht ist oder die Website stark von nativen, dynamischen Funktionen lebt.
  • Wann das SSG gewinnt: Ein modernes SSG-Setup spielt seine Stärken aus, wenn maximale Performance, höchste Sicherheit, minimale Fixkosten und ein automatisierter, ticketbasierter Freigabe-Workflow im Vordergrund stehen.

Am Ende gewinnt kein System pauschal über das andere – es gewinnt immer das Setup, das am besten zu deinem Projekt passt.

set_error_handler(): Warnungen zentral abfangen

set_error_handler() ist praktisch, wenn du PHP-Fehler nicht einfach irgendwo verstreut behandeln willst. Stattdessen reagierst du an einer zentralen Stelle auf Warnungen, Notices oder eigene Fehler.

set_error_handler(function (int $severity, string $message, string $file, int $line): bool {
    error_log("[$severity] $message in $file:$line");

    return true;
});

Warum das nützlich ist: Du bekommst einheitliches Logging und kannst viele alte Warnungen in saubere Exceptions umwandeln.

set_error_handler(function (int $severity, string $message, string $file, int $line): bool {
    throw new ErrorException($message, 0, $severity, $file, $line);
});

Besonders hilfreich bei:

  • Legacy-Code
  • Bibliotheken mit schwacher Fehlerbehandlung
  • Projekten, in denen du Fehler lieber gesammelt als stillschweigend behandeln willst

Wichtig: Nicht jeder Fehler sollte blind zu einer Exception werden. In produktiven Systemen lohnt sich ein klarer Plan, welche Fehler du hart behandelst und welche nur geloggt werden.

register_shutdown_function(): Die letzte Chance im Request

register_shutdown_function() läuft ganz am Ende des Skripts — auch dann, wenn vorher etwas richtig schiefgelaufen ist. Genau deshalb ist die Funktion so wertvoll für Logging und Notfall-Handling.

register_shutdown_function(function (): void {
    $error = error_get_last();

    if ($error === null) {
        return;
    }

    error_log($error['message'] . ' in ' . $error['file'] . ':' . $error['line']);
});

Warum das nützlich ist: Du kannst fatale Fehler noch erkennen, bevor der Request komplett verschwindet, und bekommst wenigstens ein sauberes Log.

Typische Einsatzfälle:

  • Fehlerprotokollierung
  • Cleanup von temporären Dateien
  • letzte Benachrichtigung bei kritischen Abbrüchen

Wichtig: Die Shutdown-Funktion ist keine Wunderwaffe. Wenn schon ein fataler Fehler passiert ist, ist dein Spielraum begrenzt — aber für Diagnose und Aufräumen oft genau richtig.

set_exception_handler(): Wenn nichts mehr abgefangen wird

Wenn irgendwo eine Exception durchrutscht, ist set_exception_handler() dein letzter sauberer Anlaufpunkt. Genau dafür ist die Funktion stark: Du definierst einmal zentral, was bei einem unbehandelten Fehler passieren soll.

set_exception_handler(function (Throwable $e): void {
    error_log($e->__toString());
    http_response_code(500);
    echo 'Es ist ein Fehler aufgetreten.';
});

Warum das nützlich ist: Du brauchst nicht überall denselben Fallback-Code und bekommst trotzdem einheitliches Logging sowie eine kontrollierte Antwort an den Browser.

Besonders praktisch bei:

  • APIs
  • kleinen Projekten ohne großes Framework
  • Bootstrap-Dateien, die den ganzen Request initialisieren

Wichtig: Der Handler selbst sollte sehr robust sein. Wenn dort wieder ein Fehler passiert, wird die eigentliche Ursache schnell schwerer nachvollziehbar.

TMPFS auf ~/.cache: Mehr wert als man zuerst denkt

~/.cache auf tmpfs zu legen ist auf Desktop-Systemen oft überraschend nützlich. Genau dort landen Browser-Cache, Thumbnails, Build-Reste und anderer Kram, der nach einem Neustart meist nicht wirklich fehlt.

Gerade Browser schreiben permanent kleine Dateien. Allein dadurch kommen viele unnötige Schreibzugriffe zusammen. Wenn ~/.cache im RAM liegt, ist das schneller erledigt und die SSD wird nicht dauernd mit Wegwerfdateien beschäftigt.

tmpfs /home/USERNAME/.cache tmpfs rw,nosuid,nodev,noatime,uid=1000,gid=1000,mode=700 0 0

Pfad, uid und gid musst du an dein System anpassen.

Natürlich ist tmpfs nicht gratis: Der Platz kommt aus dem RAM und nach einem Neustart ist der Cache weg. Aber genau das ist hier meistens eher ein Vorteil als ein Nachteil.

Meine Faustregel: Wenn genug RAM da ist, lohnt sich tmpfs auf ~/.cache fast immer. Schon allein wegen der Browserdateien.