Meine Website, „One Binary“ (2022)
(j3s.sh)- Wenn man eine persönliche Website als ein einziges Binary baut, kann eine einzelne Person die gesamte Struktur verstehen und selbst warten; die Abhängigkeitslast klassischer Kombinationen aus SSG und Hosting sinkt dadurch.
- Kombinationen wie Hugo und GitHub Pages setzen mehrere externe Bedingungen voraus: Fortbestand des Dienstes, Pflege des Projekts, Plugin-Ökosystem, Deployment-Methode, Go und mehr.
- Manuelles Bearbeiten von HTML ist einfach und stabil, macht es aber schwer, gemeinsame Funktionen wiederholt zu handhaben; der Workflow wurde ermüdend, daher brauchte es eine Methode, die sich angenehmer anpassen lässt.
- Eine dynamische Website auf Go-Basis erledigt Aufgaben, die bei statischen Sites umständlich sind – etwa das Anzeigen der IP-Adresse oder das Aktualisieren eines RSS-Feeds – per serverseitigem Code und liefert vollständiges HTML auch an Tools statt nur an Browser zurück.
- Persönliche Websites halten länger, wenn man klein anfängt und sie mit Standardbibliothek und einfachen Werkzeugen wachsen lässt; wer mit einem großen Framework startet, kann in der eigenen Freizeit nur schwer Schritt halten.
Warum die bisherigen Website-Tools nicht passten
- Von Ghost, Hugo, Jekyll, sr.ht mit Tarball bis hin zu manuellem HTML-Editing wurden verschiedene Ansätze ausprobiert, doch sie passten nicht zu den persönlichen Kriterien und weckten auch kein Interesse.
- Das wichtigste Kriterium war ein System, das eine einzelne Person von Anfang bis Ende verstehen und leicht warten kann.
- Gut lesbarer Code
- Schnelle Feedback-Schleife
- Spaß und Cleverness
- Eine Struktur, in die man sich bei Fehlern selbst hineingraben kann
- Statische Site-Generatoren (SSG) wie Hugo nehmen Templates und Markdown als Eingabe und erzeugen daraus HTML; üblicherweise werden sie zusammen mit einer Hosting-Plattform genutzt.
- Die Kombination aus Hugo und GitHub Pages bringt mehrere Wartungsbedingungen mit sich.
- Der GitHub-Pages-Dienst muss weiter funktionieren.
- Das Produkt GitHub Pages muss weiter gepflegt werden.
- Das Hugo-Projekt und die Community-Dokumentation müssen gepflegt werden.
- Es kann Abhängigkeiten vom Plugin-Ökosystem geben.
- Das Hugo-Binary muss auch mit der Zeit HTML auf nahezu dieselbe Weise erzeugen.
- Der Deployment-Mechanismus von GitHub Pages muss weiter funktionieren.
- Go wird benötigt.
- Man kann zwar eine bestimmte Hugo-Version festpinnen, doch in der Praxis kommt es vor, dass wegen Bugs ein Upgrade nötig wird.
Vorteile und Grenzen manueller HTML-Bearbeitung
- Gewählt wurde auch der Ansatz, die Website auf einer selbst kontrollierten Maschine zu hosten und HTML von Hand in Vim zu bearbeiten.
- Die erste Version von j3s.sh entstand auf diese Weise, und viele der heutigen Layout-Ideen stammen daraus.
- HTML von Hand zu schreiben fühlt sich wie mühsame Handarbeit an und führt zu extremem Minimalismus.
- Styles werden direkt ins HTML geschrieben.
- Gemeinsame Funktionen über die gesamte Site hinweg werden minimiert.
- Auf viel Styling wird verzichtet.
- Dieser Ansatz war einfach, stabil und leicht zu warten.
- Das geschriebene HTML ließ sich ohne Änderungen wiederverwenden.
- Es gab keine externen Abhängigkeiten.
- Er gab die Zuversicht, dass die Site lange bestehen bleibt.
- Allerdings sollte die Templatisierung gemeinsamer Funktionen effizienter werden, und es brauchte eine Methode, die sich ohne bestehendes Framework auf unterhaltsame Weise anpassen lässt.
Go-Website als einzelnes Binary
- Wenn man die gesamte Website in einer Sprache schreibt, kann man das Ergebnis in einem einzigen Binary bündeln und deployen.
- Go war eine passende Wahl für persönliche Wartung und einfaches Deployment.
- Leicht von einer einzelnen Person zu warten
- Betont einen Ansatz mit wenigen Abhängigkeiten
- Die Sprache ist vergleichsweise einfach
- Es gibt eine Garantie für Abwärtskompatibilität
- Statisch kompilierte Binaries lassen sich leicht erstellen
- Die Kompilierung dauert meist weniger als 10 Sekunden
- Die Standardbibliothek ist gut entwickelt
- Im Ergebnis wurde j3s.sh zu einem einzigen Binary, das die Website ausliefert.
Die Einfachheit dynamischer Websites
- Je nach Fall kann eine dynamisch erzeugte Website einfacher sein als eine statisch generierte.
- Man muss sich keine Umwege zur Content-Erzeugung überlegen.
- Benötigte Inhalte können direkt zur Laufzeit erzeugt werden.
- Die Funktion, die IP-Adresse eines Besuchers auszugeben, lässt sich mit Go über
http.HandlerFunceinfach implementieren.- Der Header
X-Forwarded-Forwird gelesen. - Ein Handler wird mit dem Pfad
/ipverbunden. - Dieselbe Funktion kann dort aufgerufen werden, wo sie gebraucht wird.
- Der Header
- Um dieselbe Funktion auf einer statischen Site umzusetzen, kann eine externe Abhängigkeit wie JavaScript nötig sein; außerdem muss der Fall ohne JavaScript berücksichtigt werden.
- Manche Leser lehnen die Ausführung von JavaScript ab.
- Wenn der Server bereits HTML mit enthaltener IP-Adresse zurückgibt, bekommt der Client auch dann die richtige Antwort, wenn er JavaScript nicht versteht.
- Dasselbe funktioniert auch für Tools, die keine Browser sind.
- Der RSS-Feed der Homepage wird beim Start der Website erzeugt.
- Die neuesten Beiträge von Freunden können neu abgerufen werden.
- Der selbst gebaute RSS-Feed-Fetcher dürfte lange ohne Wartung funktionieren.
- Seine interne Funktionsweise ist genau verstanden.
Deployment und Einstieg
- Das Deployment wird über ein kurzes Shell-Skript erledigt.
- Das Git-Repository wird geholt.
- Wenn der lokale Branch zurückliegt, wird
git merge origin/mainausgeführt. - Mit
go buildwird gebaut. - Das Binary wird nach
/usr/local/bin/j3s.shverschoben. - Mit
service j3s.sh restartwird der Dienst neu gestartet.
- Dieses Skript läuft jede Minute als Cronjob und baut die Site neu, sobald das Repository aktualisiert wurde.
- Wenn man lokal testet und hochlädt, ist die Änderung innerhalb einer Minute auf der öffentlichen Site sichtbar.
- Es ist so einfach, dass man es mit ein wenig Shell-Kenntnis in unter 10 Sekunden verstehen kann.
- Persönliche Websites fühlen sich im heutigen Web eigenständig an und können tief widerspiegeln, was dem Betreiber wichtig ist.
- Wer mit einer statischen Site gut bedient ist, kann dabei bleiben; für Menschen mit ähnlichen Wertvorstellungen kann der Versuch einer dynamischen Website jedoch gut passen.
- Man kann klein anfangen.
- Interessante Ideen lassen sich iterativ hinzufügen.
- Da es die eigene Site ist, darf man Dinge hart codieren.
- Man kann sie in einer Lieblingssprache wie Rust, Perl oder Python bauen.
- Der Anfang sollte klein sein.
- Zuerst
index.htmlerstellen und sich darauf konzentrieren, diese mit der gewählten Sprache auszuliefern. - RSS oder Markdown später hinzufügen, wenn sie gebraucht werden.
- Möglichst die einfachsten und am besten wartbaren Werkzeuge nutzen, etwa die Standardbibliothek.
- In Ruby kann man kleinere Optionen wie Sinatra statt Rails erwägen, in Python etwa Gin statt Flask.
- Man kann auch zuerst ausprobieren, ob es sich mit 0 Libraries selbst umsetzen lässt.
- Zuerst
- Wer mit einem großen Framework oder einem Projekt beginnt, das ständig Breaking Changes hat, kann in der eigenen Freizeit schwer mithalten und schnell ermüden.
- Das Web braucht mehr Seltsamkeit, Begeisterung und Persönlichkeit; der Versuch, eine dynamische Website zu bauen, ist empfehlenswert.
1 Kommentare
Hacker-News-Meinungen
Auf Mobilgeräten wird die Website-Breite nicht korrekt berechnet, sodass man zum Lesen nach links und rechts scrollen muss.
Direkt davor hatte ich den Satz „Ich habe sehr hohe und ungewöhnliche Maßstäbe“ gelesen, was mich ehrlich gesagt ziemlich zum Lachen gebracht hat :)
pregerendert wird und dadurch wie ein riesiger Absatz aussieht ¯_(ツ)_/¯Seltsame Formatierungen habe ich oft gesehen, aber gar keine Formatierung zum ersten Mal.
Trotzdem ist der erste Eindruck nicht gut.
Ich verstehe es nicht.
Es ist schön, dass er stolz darauf ist, aber ich habe mich einfach entschieden, es nicht zu lesen.
Entscheidend ist, was „einfach halten“ überhaupt bedeutet und was „verständlich“ bedeutet.
Solche Texte überspringen die interessante Debatte und setzen voraus, dass der eigene Ansatz einfach ist und dass Einfachheit das Ziel ist.
Wenn man Abstraktionen wählen kann, etwa Libraries oder Frameworks, Services oder APIs: Ist es einfacher, sie zu verwenden, oder einfacher, sie nicht zu verwenden?
Wenn man sie nicht verwendet und selbst baut, versteht man besser, wie das Gesamtsystem funktioniert, also ist es in gewissem Sinne einfacher.
Aber Komplexität entsteht trotzdem, und je nach Fall muss man auch die Abstraktionsschichten selbst bauen.
Verwendet man sie dagegen, wird Komplexität verborgen; im normalen Pfad kann man das System daher als einfacher betrachten, aber diese Komplexität existiert weiterhin und bleibt verborgen, sodass man sie nicht versteht.
Beide Ansätze wirken aus einer bestimmten Perspektive offensichtlich einfach, aber erst jenseits dieser Offensichtlichkeit werden die Trade-offs sichtbar.
Normalerweise kauft man Zutaten und Werkzeuge und backt ihn in einem vorhandenen Ofen.
Aber wenn man einen Apfelkuchen von Grund auf machen will, muss man zuerst das Universum erschaffen, und vermutlich würde man das einfachste Universum bauen, das Apfelkuchen unterstützt.
Der gesamte Stack mag einfacher sein, aber der letzte Schritt, nämlich tatsächlich den Kuchen zu backen, kann komplizierter werden, und vielleicht schmeckt er auch nicht überragend.
Dafür bekommt man einen Kuchen, den man vollständig aus First Principles heraus versteht.
Vielleicht gefällt dir dieser Vortrag von Rich Hickey: https://paulrcook.com/blog/simple-made-easy
Man kann Funktionen hinzufügen, um etwas leichter zu machen oder zu deployen, aber durch diese Ergänzungen wird das Ganze komplexer und schwieriger zu verstehen oder bei Problemen nachzuverfolgen.
Der Autor sagt am Ende sehr klar, dass jeder es auf seine Weise machen soll.
Außerdem sagt er, dass er nicht damit zufrieden ist, Systeme zu verwenden, die er schwer verständlich oder belastend findet.
Es wäre gut, auch über den ersten Absatz hinaus zu lesen.
Sehr cool!
Dem „Ihr solltet das auch so machen!“ stimme ich absolut nicht zu :)
Wartbarkeit ist einer meiner zentralen Werte, deshalb warte ich wie du auch mein Fahrrad selbst.
Aber für mich hat sie nicht in diesem Maße Priorität 1, daher ergeben solche Entscheidungen für mich keinen Sinn.
Das Framework-Laptop ist ein guter Punkt, an dem sich unser Unterschied zeigt.
Du erreichst auf der DIY-Seite durchgehend eine 9, während ich Resilienz dadurch absichere, dass ich einen 10 Jahre alten ThinkPad-Ersatzrechner habe, auf dem ich jederzeit schnell Linux und Neovim starten kann; und falls selbst der kaputtgeht, vertraue ich darauf, dass es auch künftig viele ThinkPads für unter 100 Dollar geben wird.
Ich trage genug Informatik- und Mathematikwissen mit mir herum, um, falls es eines Tages nötig wird, mit Haskell-Kombinatoren einen langsamen, inoffiziellen und fehlerhaften Parser von Markdown nach HTML zu schreiben, aber ich glaube nicht, dass dieser Tag bald kommt.
Wenn möglich, würde ich dich gern einstellen.
Du wärst das perfekte Gegengewicht zu den vielen Menschen, die in die entgegengesetzte Richtung kippen.
Ich habe diesen Artikel wirklich gern gelesen.
Der Autor ist ehrlich zu sich selbst und ernsthaft gegenüber den Lesern.
Er ist ohne Ausflüchte er selbst und versucht, seine Ziele auf eine Weise zu erreichen, die zu seinen Werten passt und ihm Freude bereitet.
Es ist in Ordnung, wenn diese Werte nicht zu deinen passen; eigentlich ist genau das etwas Schönes.
Jetzt hast du einen Hinweis auf einen Weg bekommen, den du erkunden kannst.
Der Text ist freundlich, bescheiden und authentisch, und ich glaube, dass der Autor und der Text die Welt ein kleines bisschen besser machen.
Mit „bescheiden“ ist es genauso.
Der ganze Text kommt eher einer Selbstbeweihräucherung nahe, und zwischendurch sieht man auch Fragmente im Stil von /r/confidentlyincorrect.
Die Leser sind nur ein Nebenschauplatz; deshalb ist es nicht der Kern der Sache, egal wie spartanisch die Leserfahrung ist — die Erfahrung des Autors ist der Kern.
Viele Leute von mobilen Plattformen scheinen das Lesen zu früh aufgegeben zu haben.
Ich habe es grob überflogen, und diese Person trollt uns ziemlich sicher.
Die Website behauptet, wörtlich „plain HTML“ zu verwenden, ist in Wirklichkeit aber plain text.
Es gibt dort überhaupt kein HTML für Formatierung.
Keine Überschriften, keine Absätze, keine Listen und nicht einmal a-Tags.
Das bisschen HTML und CSS, das enthalten ist, lässt die Site sogar schlechter rendern.
Der Autor ist ein Troll.
Er sagt: „Ich habe sehr hohe und ungewöhnliche Standards“ und: „Dieses Skript läuft jede Minute als Cronjob und baut die Site neu, wenn das Git-Repository aktualisiert wurde.“
Das heißt, ein Repository, in das vielleicht ein paar Commits pro Jahr gehen, wird 525.600-mal pro Jahr geholt.
Ich verstehe, warum das Wort „ungewöhnlich“ dabei ist.
git fetchim Grunde fast nur ein String-Vergleich [0], daher halte ich es nicht für so teuer, wie es klingt.[0] https://stackoverflow.com/a/44476803
Das sollte man einem nicht auf Nachfrage sagen müssen, sondern ungefragt mitteilen.
Meine Git-Repositories liegen alle auf demselben Server, der auch die Website hostet.
Git macht keinen Remote-Fetch, sondern einen lokalen Fetch, der praktisch sofort fertig ist.
Selbst wenn es ein Remote-Fetch wäre, wäre es in Ordnung.
525.600 HTTP-Requests pro Jahr sind weniger verschwenderisch als der Heartbeat von NetworkManager.
Unter Arch ist der Standard ein Heartbeat-Request alle 30 Sekunden.
Zur Einordnung: Ein einfacher nginx-Server mit 8 CPUs kann mehr als 500.000 HTTP-Requests pro Sekunde verarbeiten.
An den OP:
Hier gibt es ziemlich viel sehr kritisches Zeug.
Höflich gesagt … kümmere dich nicht darum.
Die Kritik mag richtig sein, aber die Branche steuert, indem sie kollektiven „Man muss“- und „Das gehört sich so“-Vorstellungen folgt, schnell auf Dummheit im großen Maßstab zu.
Vieles davon hat derzeit kaum mehr Plausibilität als eine Großstadtlegende.
Was heutzutage „Engineering“ genannt wird, wäre zum Lachen, wenn wir nicht aktiv unsere Zukunft darauf aufbauen würden.
Mein Vater war Luft- und Raumfahrtingenieur; bei dem, was in der modernen Softwareentwicklung Engineering genannt wird, würde er sich wohl im Grab umdrehen.
Es ist ein Kommentarbereich, also kann jeder sagen, was er will, aber persönlich habe ich erst nach 25 Jahren in der Branche gelernt, diese geschwätzigen Stimmen zu ignorieren und, bei den seltenen Gelegenheiten, bei denen es möglich ist, das zu tun, was sich für mich sinnvoll anfühlt.
Und bei einer persönlichen Website gilt das doch erst recht, oder?
Der alte Satz aus der Apple-Werbung, „für die Verrückten“, klingt inzwischen weit von der Wahrheit entfernt.
Kein Wunder, wenn das Internet so geworden ist und die einstigen Startups heute die größten Konzernmonster der Landschaft sind.
Theodore Roosevelts Zitat vom „Mann in der Arena“ trifft heutzutage wirklich zu.
Mach weiter, OP, mach weiter …
Meine Website ist keine perfekt optimierte Site, sondern mein eigenes heiliges und eigenwilliges Spielgelände.
Alles ist selbst geschrieben und entwickelt sich mit der Zeit weiter.
Mir ist klar, dass mein Stil manchen Leuten gegen den Strich geht, und an solche Kritik bin ich gewöhnt.
Ich treffe auch seltsame Entscheidungen, um Inhalte in eine Form zu biegen, die mir gefällt, aber genau das macht meine Inhalte meiner Meinung nach liebenswert.
Weil sie nicht wie alles andere da draußen sind.
Es wird raue Kanten geben, aber beim Erkunden einer „persönlichen Form“ wird es nach und nach besser werden :)
Für mich ist die Website wie ein langfristiges Kunstprojekt.
Sie sollte den Autor ausdrücken, und in meinem Fall drückt meine Site ganz unverblümt mich aus.
Da du deine gezeigt hast, zeige ich auch meine.
Meine Website, Game-Engine und Webserver sind eine einzige Binary.
Der Quellcode besteht aus 1000 Zeilen C, die Binary ist 164 KB groß.
Ich weiß nicht, warum sie verdammt noch mal so groß ist.
Den Webserver habe ich ebenfalls selbst eingebaut.
Bestehende Server bringen zu viel versteckte Komplexität mit.
Das Ergebnis, ein deutsches Interactive-Fiction-Spiel, ist hier zu sehen: http://vmd34232.contaboserver.net/
Kein Tracking, keine Werbung, keine kommerziellen Ziele.
Die ausführbare Datei könntest du mit upx komprimieren: https://upx.github.io/
https://toldby.ai/
Meine ist keine einzelne Binary, sondern asp.net.
Ich stimme allen im Artikel angesprochenen Punkten völlig zu, aber diese Website ist als Beispiel eher schlecht.
Die Website wird als „eine einzige Binary“ bezeichnet, aber die Deployment-Strategie umfasst das Kompilieren, statt ein Binary-Artefakt auszuführen.
Es heißt, man wolle sich nicht auf github pages verlassen, verlässt sich aber auf externe Ressourcen von openlibrary.org.
Es heißt, wenn man selbst baut, könne man offene Standards nutzen, aber die
.html-Dateien inthoughts/sind einfache Textstrukturen mit falscher Dateiendung.Wenn Leute diesen Weg wählen, versuchen sie meist, alles in den initialen Page Load zu packen; hier gibt es jedoch mehrere dynamisch ausgelieferte statische Dateien.
Der Golang-Code cached keine Antworten und hält auch keine Templates im Speicher.
In der Datei
go.modstehen mehrere Abhängigkeiten, die offenbar alle ungenutzt sind.Am wichtigsten: Es gibt keine Diskussion darüber, welche technischen Vorteile der Single-Binary-Gedanke gegenüber moderner Infrastruktur hat.
Persönlich halte ich das für eine gute Idee, aber dies ist ein schlechtes Beispiel.
Es ist eine einzelne Binary, die mit dem Dateisystem zusammenarbeitet.
Sämtlicher Inhalt liegt im Dateisystem.
Die „einzelne Binary“ ist ein leichtgewichtiger Golang-Webserver, der Inhalte aus dem Dateisystem ausliefert.
„Sehr hohe und ungewöhnliche Standards“ heißt es, und ungewöhnlich ist es tatsächlich, aber das resultierende Website-Design ist so miserabel, dass es den Text nicht einmal ordentlich passend zum Bildschirm anzeigen kann; die Standards sind also eher sehr niedrig.