Tipps & Tutorials

Moderne, leichtgewichtige Dokumentationen mit VitePress erstellen


Veröffentlicht am 20.06.2023 von David Würfel

In vielen Softwareprojekten einer bestimmten Größe und einer gewissen Anzahl an Mitarbeitenden besteht die Notwendigkeit, Informationen nachhaltig zu dokumentieren. Sei es zum erleichterten Onboarding neuer Teammitglieder, zur Nachvollziehbarkeit von Architekturentscheidungen oder zur gebündelten Visualisierung komplexer Strukturen innerhalb der manchmal schwer greifbaren Softwarestruktur. Eine große Herausforderung dabei ist es, diese Informationen stets aktuell zu halten und sie so zu organisieren, dass alle Mitarbeitenden schnell und intuitiv darauf zugreifen können.

Anbieter gängiger, meist kostenpflichtiger Projektmanagement-Lösungen stellen hier häufig Produkte bereit, die außerhalb des eigentlichen Quellcodes der Software liegen. Das kann dazu führen, dass Dokumentation und tatsächlicher Stand der Software relativ schnell auseinanderlaufen oder nur durch sehr strikte Prozesse aktuell gehalten werden können. Viele dieser Systeme bieten nicht immer einfach zugängliche Schnittstellen an, um automatisiert mit den Daten der Dokumentation zu interagieren: manche Teile der Dokumentation sollen generiert werden, die Dokumentation soll in andere Quellen eingebunden oder regelmäßig auf Plausibilität geprüft werden. 

Um diesen Nachteilen entgegenzuwirken, empfiehlt es sich, die Dokumentationsdaten so nah wie möglich oder sogar als Teil des Codes der Software und in einem Format anzulegen, welches leicht maschinenverarbeitbar ist. Dies kann z.B. in Form von Markdown, JSON o.ä. in einem entsprechenden Unterordner als Teil des Code-Repositories umgesetzt werden. Im Gegensatz zu oben genannten Lösungen braucht es hier wiederum eine entsprechende Aufbereitung, Einbindung der Dokumentation in bestehende Organisationsstrukturen und Sicherstellung der Erreichbarkeit für alle Projektbeteiligten.

Im Rahmen dieses Artikels wollen wir uns mit VitePress ein Werkzeug ansehen, welches wir dazu nutzen, moderne, leichtgewichtige Dokumentationen zu erstellen, die wir sowohl in gängigen Formaten direkt als Teil des Software-Repositories anlegen als auch eine einfache Zugänglichkeit für alle erreichen können. Nicht zuletzt kann VitePress spezielle Bedürfnisse durch zahlreiche Möglichkeiten der automatisierten Verarbeitung und Aufbereitung erfüllen.

VitePress, ein Static Site Generator

VitePress als geistiger Nachfolger von VuePress, ist ein relativ neues Werkzeug, das sich zum Zeitpunkt dieses Artikels noch in den letzten Zügen der Alpha-Phase befindet. Es ist ein Vite- und Vue-basierter sogenannter Static Site Generator (SSG), d.h. ein Bündel von Werkzeugen, mit denen auf Grundlage des Build-Tools Vite und des JavaScript Frontend-Frameworks Vue.js am Ende eine statische Webseite entsteht. Im Gegensatz zu einer klassischen Vue-Applikation handelt es sich hierbei nicht um eine Single-Page-Applikation, sodass der eigentliche Inhalt der Seite nicht erst beim Besuch dynamisch durch Skript-Code zusammengesetzt wird. Diese Eigenschaft möchte man immer dann nutzen, wenn sich der Seiteninhalt relativ selten ändert und es wesentlich ist, dass automatisiert stets auf den gesamten Seiteninhalt durchsuchbar zugegriffen werden kann, beispielsweise bei Blogs, jeglicher Art von Dokumentation oder Nachrichten- und Produktseiten.

Mit Hugo, Next.js oder weiteren gibt es eine Vielzahl von SSGs, die schon länger existieren und teilweise über einen deutlich größeren Funktionsumfang als VitePress verfügen. Zum Begegnen der oben beschriebenen Herausforderung, der Erzeugung von softwarebezogener Dokumentation, die man zudem durch Entwickeln kleiner Vue-Komponenten anreichern kann, möchte ich meine eigenen Erfahrungen mit VitePress als schlankes, modernes Tool teilen.

Das Dokumentation-Projekt

Wir nehmen zunächst an, dass es eine bestehende Software gibt. Beispielsweise eine Applikation, mit der wir absolvierte Projekte in unserem Unternehmen am Ende des Jahres auswerten und uns anhand von Diagrammen ansehen können – nennen wir sie Retroject. Wir verfügen über ein Mono-Repository retroject mit entsprechendem Quellcode. Darin wollen wir nun einen Ordner /documentation erstellen, der die gesamte für das Projekt relevante Dokumentation beinhaltet.

Wir befinden uns per Kommandozeile in entsprechendem Repository und erzeugen über den folgenden Befehl ein neues Vite-Unterprojekt:

Anschließend fügen wir (orientiert an der offiziellen VitePress-Dokumentation) nützliche NPM-Skripte hinzu, sodass wir schließlich folgende package.json vorfinden:

Erste Schritte

Bevor wir nun über npm start unser Ergebnis im Development-Modus ansehen können, sollten wir eine allererste Seite anlegen. Standardmäßig liegen die Seiten in VitePress als Markdown-Dateien im Unterordner /docs. Auch wenn dies anpassbar ist, sehen wir keine Notwendigkeit, eine andere Ablagestruktur zu verwenden und erstellen die Einstiegsseite /docs/index.md mit erstem Inhalt:

Abbildung 1 - VitePress erstellen Erste Schritte

Zugegebenermaßen ist dies (Abbildung 1) noch nicht sonderlich beeindruckend, denn jedes README.md eines normalen GitHub-Projekts bietet die gleichen Möglichkeiten. Die wahren Stärken, wie z.B. den Einsatz der verschiedenen VitePress-Funktionen bis zum Entwurf eigener Komponenten, die wir einbinden können, schauen wir uns nun genauer an.

Navigationsleisten und weitere Seiten anlegen

Wie auf der Einstiegsseite zu erahnen ist, gibt es verschiedenen Themenbereiche innerhalb unserer Dokumentation, z.B. ein Einstieg für Neuzugänge, technische Inhalte oder eher organisatorische Informationen. Wir legen nun weitere Inhalte an und möchten diese Struktur in einer Seitenleiste abbilden (Abbildung 2).

Nachdem wir beispielsweise unter /docs/onboarding/index.md, /docs/technical/decisions.md und /docs/technical/architecture.md weitere Inhalte angelegt haben, sind diese zwar über ihre URLs erreichbar, für den Nutzer der Dokumentation jedoch noch nicht sichtbar. Meta-Informationen, wie die Konfiguration der Navigationsleiste werden in der Datei /.vitepress/config.ts vorgenommen. Neben dem Titel der Dokumentationsseite fügen wir hier unterhalb der Eigenschaft themeConfig auch das Projektlogo und eine erste Struktur für die Navigation ein:

Das Logo-PNG sollte über einen absoluten Pfad angegeben werden und kann dabei unterhalb des Ordners /docs liegen. Bei der Angabe der Links in der Navigationsleiste ist zu beachten, dass ein Link auf die jeweilige Einstiegsseite index.md jeweils nur den Pfad zum Oberordner angibt, jedoch mit Schrägstrich (/) endet. Die Angabe des Dateityps sollte man nicht vornehmen, da bei der Generierung die md-Dateien ohnehin zu html-Dateien umgewandelt werden. Wir können nun auch auf unserer Einstiegsseite auf die weiteren Seiten verlinken. Dies kann dabei relativ zur Dokumentationsseite geschehen:

Abbildung 2 - VitePress erstellen - Dokumentationsseite

Verwenden weiterer nützlicher VitePress-Funktionen

Je nach konkreten Inhalten, die durch die Dokumentation abzubilden sind, gibt es nun Anforderungen, die sehr verschieden und von einfach bis komplex reichen können. Ein paar der gängigsten Fragestellungen wollen wir uns im Folgenden ansehen.

Einbinden von Bildern und Diagrammen

Nehmen wir an, dass wir im Architektur-Bereich ein Diagramm über die Software-Architektur anfügen wollen (Abbildung 3). Dieses liegt uns im einfachsten Fall als PNG zur Verfügung. Das Bild kann mit regulären Mitteln von Markdown eingebunden werden. Dabei bietet es sich hier an, das Bild relativ zur Dokumentationsseite und direkt nebenan in der Ordnerstruktur abzulegen.

Abbildung 3 - Übersicht über die Softwarearchitektur

In diesem Fall wurde das Bild vorher manuell erstellt. Selbstverständlich könnte man dieses Bild auch innerhalb eines Build-Prozesses automatisch generieren lassen, z.B. könnte ein Analysewerkzeug aus dem tatsächlichen Quellcode ein Diagramm generieren, welches stets aktualisiert und eingebunden wird.

Einbinden von Quellcode

In einer Software-Dokumentation findet man häufig auch Quellcode-Schnipsel, um gegebenenfalls Konfigurations-Parameter zu erläutern oder Beispiele zur Verwendung von UI-Komponenten zu liefern. Dabei kann man wie folgt direkt Quellcode-Schnipsel verwenden und dabei u.a. bestimmte Zeilen hervorheben (Abbildung 4):

 

Abbildung 4 - VitePress - Magic-ValuesSoeben haben wir den Schnipsel direkt in die Dokumentation eingetragen. Oft möchte man jedoch existierende Quellcode-Dateien einbinden. Der Inhalt muss dabei nicht kopiert werden; die Datei kann direkt über entsprechende Syntax eingebunden werden:

Abbildung 5 - NPM-Skripte

Hierbei können auch wieder bestimmte Zeilen hervorgehoben werden (Abbildung 5). Leider ist es aktuell nicht möglich, nur bestimmte Bereiche herauszuschneiden, ohne den Quellcode selbst zu verändern. Denn um dies zu erreichen, muss man in der Originaldatei sogenannte VSCode Regions platzieren, die man dann wiederum bei der Einbindung anspricht.

Weitere Markdown-Erweiterungen

Neben den gerade vorgestellten Techniken gibt es noch eine ganze Reihe weiterer nützlicher Markdown-Helferlein, die man der VitePress-Dokumentation entnehmen kann, beispielsweise zur Integration von Emojis oder dem Setzen von Hinweis- oder Warn-Boxen.

Vorgefertigte VitePress-Bausteine

Neben der Nutzung von speziellem Markdown bringt VitePress Komponenten mit, die man häufig beim Schreiben von Blogs oder Dokumentationen benötigt.

Der generelle Einstieg auf die Dokumentation soll eine erste Orientierung bieten und ist dadurch häufig anders aufgebaut. Hierfür liefert VitePress einen vorgefertigten Homepage-Baustein. Über Frontmatter, einen besonderen Abschnitt, geschrieben in YAML-Syntax zu Beginn einer jeden Markdown-Datei, lassen sich Metainformationen zu einer Seite angeben. Zur Konfiguration einer Homepage schreibt man ausschließlich ein paar Zeilen dieses YAML-Codes, und VitePress stellt diese über gegebene Komponenten dar. Wir können unsere einfach gestaltete Einstiegsseite dadurch ersetzen und erhalten so einen optisch ansprechenden Einstieg für unsere Leser:innen:

Abbildung 6 - VitePress Retroject DokumentationInsbesondere in größeren Organisationen ist eine Team-Seite interessant für die Software-Dokumentation. Diese enthält Informationen zu den Projektbeteiligten, wie beispielsweise ihre Namen, ihre Rollen und Aufgaben, einen Avatar oder Kontaktinformationen. Über etwas Skript-Code und die Einbindung der von VitePress bereitgestellten Vue-Komponente VPTeamMembers innerhalb einer Markdown-Datei kann man schnell eine optisch ansprechende Übersicht des Projektteams erstellen (Abbildung 7):

Abbildung 7 - VitePress Retroject ProjektteamGerade für Open-Source-Projekte interessant sind auch die vorgefertigten Sozial-Links, bei denen man über die Angabe des Dienstes wie GitHub, LinkedIn o.ä. direkt das passende Icon samt Link zur Profilseite anzeigen kann.

Eigene Vue-Komponenten nutzen

Wirklich mächtig wird VitePress genau dann, wenn man spezifische Anforderungen zu erfüllen hat und diese durch gezielten Einsatz von eigens dafür geschriebenen Vue-Komponenten lösen kann.

Nehmen wir an, wir wollten für unsere Rechtsabteilung eine stets aktuelle und einfach zugreifbare und konsumierbare Übersicht über die Abhängigkeiten erster Ordnung in unserem Projekt samt Lizenzinformationen haben. Die Abhängigkeiten selbst stehen bereits in der package.json, die dazugehörige Lizenzinformation muss allerdings erst ermittelt werden. Die visuelle Aufbereitung für die Dokumentation können wir mit Hilfe einer genau dafür ausgerichteten Vue-Komponente umsetzen. Die automatisierte Ermittlung dieser Informationen müssen wir in ein vor dem Build durchzuführendes Skript auslagern. Das liegt u.a. daran, dass wir in VitePress als Static-Site-Generator keine Node-APIs nutzen können. Diese brauchen wir jedoch, um unsere lokale package.json auszulesen.

Wir können uns ein kleines Node-Programm schreiben, welches wir per ts-node als prebuild-Schritt immer vor dem Erzeugen der Dokumentation ausführen (Code-Beispiel 11). Es sorgt dafür, dass eine JSON-Datei erstellt wird, die für jede Abhängigkeit die aktuelle Lizenz sammelt (Code-Beispiel 12).

Das Ergebnis können wir dann als Eingabe in unsere Vue-Komponente geben. In VitePress kann man eigene Vue-Komponenten benutzen, indem man diese innerhalb eines script-Tags im Markdown importiert und dann dort mit Hilfe von Vue-Template-Code nutzt:

In der eigentlichen Komponente (Code-Beispiel 14) erwarten wir dann jeweils für beide Arten der Abhängigkeiten ein Objekt mit den Namen der Abhängigkeiten als Schlüssel und der Lizenz-Information als Wert, also genau der Information, die wir in unserer JSON-Datei generiert haben.

Abbildung 8 - VitePress - Lizenz-Übersicht

Als Ergebnis erhält man eine tabellarische Auflistung der Projektabhängigkeiten von Retroject. Diese Darstellung ist auch für Personen außerhalb des Entwicklungsteams einfach konsumierbar (Abbildung 8).

Moderne, leichtgewichtige Dokumentationen mit VitePress - Fazit und Ausblick

Mit relativ wenigen Schritten haben wir in kurzer Zeit eine ausbaufähige Dokumentationsstruktur erschaffen, die sogar ein paar besondere Anwendungsfälle wie die automatische Erzeugung einer Lizenzübersicht umsetzt. Da die Umsetzung mit VitePress sowohl mit Markdown und Vue und damit genau den Entwicklungswerkzeugen arbeitet, die eventuell sowieso schon im Einsatz sind, und die eigentlichen Dokumentationsdaten ebenso im Repository liegen, ist, wie angedeutet, eine hohe Aktualität und Automatisierung erreichbar. 

Dieser Artikel bietet einen ersten Einblick in die Möglichkeiten, die noch darüber hinausgehen. Beispielsweise lässt sich die äußerlich ansprechende, aber recht neutral gehaltene Darstellung durch eigene Themes nach Belieben anpassen (inklusive der Bereitstellung eines Dark-Themes). Darüber hinaus sollte man die regelmäßige, automatische Auslieferung und Integration der Dokumentation in andere Systeme betrachten. VitePress wurde hier zur Erzeugung einer Software-Dokumentation genutzt, lässt sich aber darüber hinaus natürlich auch zur Umsetzung eines klassischen Blogs oder einer einfachen Webseite einsetzen. 

Als kleine Übung für Sie als Leser:in sei Ihnen nun der leichtgewichtige Einsatz dieses modernen Werkzeugs auch in anderen Bereichen überlassen. Der vollständige Quellcode zu diesem Artikel findet sich auf GitHub.

Titelmotiv: Photo by Ryland Dean on Unsplash

Der Autor:


David Würfel

David Würfel ist Softwareentwickler mit einem Faible für Web-Technologien und die Frontend-Entwicklung. Er unterstützte als Full-Stack-Entwickler und Scrum Master die embedded data GmbH in der Produktentwicklung der IIoT-Software-Plattform da³vid vor allem mit Vue und TypeScript. Zuvor arbeitete David lange als Design Engineer in der User Experience Dienstleistungs-Branche und hat gemeinsam mit der Centigrade GmbH am Standort Saarbrücken den Bereich der Webentwicklung als Field Lead aufgebaut. Sein Wissen teilt David gerne intern wie extern beispielsweise in Blogs oder freiberuflich als Trainer und bringt sich gerne in die Community ein. In seiner Freizeit entspannt er handwerklich, kreativ beim Bemalen kleiner Plastikfiguren, versucht sich musikalisch am Schlagzeug oder sucht eher digitale Herausforderungen beim Gaming an Konsolen.