Zum Inhalt springen
duxt

Den SEO-Unterbau aus dem Nuxt-SEO-Bündel nehmen

Die Ebene installiert @nuxtjs/seo und übergibt ihm die Head-Tags und strukturierten Daten, die sie bislang von Hand schrieb — behalten werden nur die Regeln, die von Versionen und Übersetzungen abhängen.

Kontext

Die Ebene lieferte bereits drei Module aus Nuxt SEO aus — robots, sitemap und OG-Image —, jedes einzeln gewählt, als der Bedarf auftauchte. Alles, was sie nicht abdecken, war handgeschrieben: ein Canonical-Link, ein og:/twitter:- Block pro Seite und ein @graph aus JSON-LD, das in [...slug].vue in einem Template-String zusammengesetzt wurde.

Das funktionierte und war unsichtbar. Genau darin liegt das Problem: Nichts davon war durch einen Test abgedeckt, weil SEO im gerenderten HTML lebt und nicht in Logik — und die Tests dieses Repos decken bewusst nur reine Logik ab. Die Startseite, also die Seite, die am ehesten geteilt wird, hatte überhaupt keine Social Card, die Fehlerseite war indexierbar, und sieben Locales wurden ohne ein einziges og:locale ausgeliefert. Jede dieser Lücken war ein Versäumnis, das niemand sehen konnte.

Die handgeschriebene Hälfte war zugleich die, die wächst. Strukturierte Daten sind eine Spezifikation mit großer Oberfläche und eigenen Validatoren; jeder von Hand ergänzte Knoten ist ein Knoten, dessen Form man sich aus der Spezifikation erlesen muss.

Entscheidung

Die Ebene hängt von @nuxtjs/seo ab und lädt es als ein Modul, an der Stelle, an der die drei benannten Module standen — vor @nuxt/content, weil die Content-Integration der Sitemap das verlangt.

Das Bündel ist ein Alias, kein Wrapper: Seine eigene Dokumentation stellt fest, es „enthält keine eigene Logik". Was es einbringt, sind die vier fehlenden Module — nuxt-schema-org für den Graphen, nuxt-seo-utils für den automatischen Canonical und die abgeleiteten Social-Tags, nuxt-link-checker sowie nuxt-site-config als die eine Stelle, aus der site.url gelesen wird — dazu das gemeinsame Devtools-Panel, das über die jeweils installierten berichtet.

Drei Vorgaben von nuxt-seo-utils werden abgeschaltet, jede aus einem Grund, den die Ebene nicht wegkonstruieren kann: canonicalLowercase, weil ein Locale-Präfix Groß- und Kleinschreibung unterscheidet und /de-DE/ nicht /de-de/ ist; fallbackTitle, weil ein aus einem Slug erfundener Titel den Build-Validator verdecken würde, der über eine Seite ohne Titel fehlschlägt; und mergeWithSiteConfig, weil app.vue das Titel-Template besitzt.

Handgeschrieben bleibt, was die Module nicht wissen können: Der Canonical einer versionierten Seite zeigt auf die aktuelle Version statt auf die gerade gerenderte Seite, und noindex folgt daraus, dass eine Version alt ist oder eine Seite in einer Sprache ausgeliefert wird, in die sie nicht übersetzt wurde.

Die Link-Prüfung berichtet, statt fehlzuschlagen. modules/validate.ts lässt einen Build bereits über einen ins Leere zeigenden Link scheitern, und es ist diejenige Prüfung, die Versionen und Sprach-Rückfälle versteht.

Konsequenzen

Jeder Konsument der Ebene installiert sieben Module statt drei. Das ist der Preis der Entscheidung, und ihn zahlen auch Sites, die keines der vier neuen nutzen.

Die Regeln, die bisher Behauptungen in einem Kommentar waren, sind jetzt Zusicherungen in scripts/check-seo.ts: Das Skript liest die gebauten Seiten und schlägt über einen zweiten Canonical fehl, über ein fehlendes hreflang, über eine indexierbare Fehlerseite oder über einen Graphen, der nicht parst. Es läuft in check neben check:a11y, aus demselben Grund — die Tags existieren nur im gerenderten HTML.

Zwei dieser Regeln waren vorher überhaupt nicht prüfbar, weil sie erst existieren, wenn die Site ihre eigene Herkunft kennt, und www bewusst keine Domain nennt. Die Prüfung übergibt dem gebauten Server dafür seine eigene Adresse über die Umgebungsvariablen, die die Module ohnehin lesen — statt einer Domain in einer Konfiguration, die ein Konsument abschreiben würde.

Eine Organization zu veröffentlichen braucht eine Tatsache, die die Ebene nicht erfinden darf, also wartet sie auf einen neuen Schlüssel duxt.organization und bleibt abwesend, bis ein Konsument ihn füllt — dieselbe Haltung wie in ADR-0005.

Erwogene Alternativen

Die drei Module behalten und nur nuxt-schema-org ergänzen. Die schmalste Änderung, verworfen am Canonical: Die Versionsregel und der automatische Canonical müssen ohnehin miteinander vereinbart werden, und ohne nuxt-seo-utils bedeutet das, den handgeschriebenen og:/twitter:-Block zu behalten, der auf zwei Seiten bereits vergessen worden war.

Die strukturierten Daten von Hand schreiben und behalten. Es funktionierte, es hatte keine Abhängigkeit, und es wurde verworfen, weil der Graph ohnehin der Teil war, der am ehesten falsch und am wenigsten bemerkt wird — und weil eine zweite Seite mit einem zweiten Knoten eine zweite Kopie der Identität der Site in sich hinein bedeutet hätte.

Den Link-Checker den Build brechen lassen. Verworfen, weil zwei Wächter über einer Regel bedeuten, dass der laschere entscheidet, wann ein Build bricht. Die Prüfung, die die Versionen und Sprach-Rückfälle dieser Ebene versteht, ist ihre eigene.

War diese Seite hilfreich?