Skip to content

0003 — Projektkonfiguration als virtuelles Modul bereitstellen

Status: angenommen · Milestone: M3

Kontext

Ab dem Layout brauchen Komponenten Werte aus der Projektkonfiguration: die Sprache für das lang-Attribut, die Titelvorlage, die Fallback-Beschreibung. Später kommen die GTM-Container-ID, der Formular-Endpunkt und die SEO-Schalter dazu — praktisch jede Komponente der folgenden Meilensteine liest daraus.

Der naheliegende Weg wäre ein relativer Import:

astro
---
import project from '../../project.config';
---

Das kollidiert mit der Fixture-Strategie aus ADR 0002. Fixture-Builds werden über astro build --config tests/fixtures/configs/full/astro.config.ts gestartet. Diese Konfiguration importiert eine andere project.config.ts. Ein fest verdrahteter relativer Import in einer Komponente zeigt aber weiterhin auf den Projektstamm: Der Build liefe mit der Fixture-Konfiguration, die Seiten würden die Werte des Starters rendern. Die Absicherung der Feature-Flags wäre damit wertlos — und der Fehler wäre still.

Entscheidung

Die Integration stellt die geprüfte Konfiguration als virtuelles Vite-Modul unter virtual:project-config bereit. Komponenten importieren ausschließlich darüber:

astro
---
import project from 'virtual:project-config';
---

<html lang={project.site.locale}></html>

Das Modul wird erst nach bestandener Prüfung registriert. Eine ungültige Konfiguration kommt gar nicht erst in den Komponenten an.

Die Typen liefert src/virtual-modules.d.ts, sodass astro check den Import kennt.

Begründung

Weil die Integration ohnehin die aktive Konfiguration als Argument bekommt, ist sie die einzige Stelle, die verlässlich weiß, welche Konfiguration gerade gilt — unabhängig davon, über welche Datei der Build gestartet wurde. Damit stimmen Fixture-Build und gerendertes Ergebnis zwangsläufig überein, statt es nur zu sollen.

Der Weg über ein virtuelles Modul ist außerdem der Punkt, an dem sich später Werte ableiten lassen, ohne jede Komponente anzufassen.

Verworfene Alternativen

Relativer Import von project.config.ts in Komponenten. Einfach, aber macht die Fixture-Builds wirkungslos — und zwar unbemerkt, weil beide Builds durchlaufen.

Konfiguration über Astro.locals oder einen Layout-Prop weiterreichen. Erzwingt, dass jede Seite die Werte durchreicht. Bei statischer Ausgabe gibt es keinen Anlass für eine Laufzeit-Weitergabe.

Werte in astro:env spiegeln. astro:env ist für umgebungsabhängige Werte und Geheimnisse gedacht, nicht für strukturierte Projektdaten. Verschachtelte Objekte lassen sich dort nicht abbilden, und es entstünde eine zweite Wahrheit über dieselben Angaben.

Konsequenzen

  • Ein direkter Import von project.config.ts in src/ ist ein Fehler. Ab M4, wenn mehrere Komponenten die Konfiguration lesen, sichert eine Lint-Regel das ab.
  • Die Werte im virtuellen Modul sind öffentlich: Sie landen im ausgelieferten HTML und JavaScript. Geheimnisse gehören ausschließlich in astro:env mit context: 'server'.
  • Das Modul wird über JSON.stringify serialisiert. Funktionen oder Klassen sind in der Projektkonfiguration damit ausgeschlossen — bislang enthält sie ohnehin nur Daten.