Mittwoch, 17. April 2024
Wochen-Ziele:
-
Blog-Grundgerüst steht und ich kann bloggen bis der Arzt kommt
Tages-Ziele:
-
Frontmatter gescheit extrahieren -
Custom CSS-Styles in gerenderte MDX-Files laden - atemberaubende Readme erstellen
Frontmatter gescheit extrahieren
Heute wollte ich mich noch mal um die Frontmatter kümmern. Oder um das Frontmatter? Oder um den?! Wer weiß... egal. Die Frontmatters halt. Kruzifix!
Jedenfalls wurde der/die/das Frontmatter bisher nicht richtig extrahiert und vom eigentlichen Content in der MDX-Datei getrennt.
Wenn das nicht klappen solle würde, müsste ich zur Not gray-matter installieren und einrichten oder es mit einem Meta-Daten-Objekt lösen. Diese Möglichkeit bietet next/mdx auch.
Weitere Packages wollte ich gerne vermeiden, weil es eigentlich mit next-mdx-remote funktionieren sollte...
Ich habe es dann doch hinbekommen. Problem war, dass sich in der MDX-Datei ein auskommentierter Komponenten-Import befand. Damit kam der MDX-Compiler von next-mdx-remote offensichtlich nicht klar. Kommentar gelöscht, Frontmatter funzt.
Custom CSS-Styles in gerenderte MDX-Files laden
Als nächstes habe ich mich an die nicht funktionierenden Custom-Styles gemacht. Man kann mit next-mdx-remote benutzerdefinierte Komponenten erstellen und diese den vom Markdown in HTML übersetzten Tags zuweisen. Ich glaube das war jetzt ziemlich unverständlich. Hier mal ein Beispiel aus meiner src/components/mdx-remote.tsx:
// src/components/mdx-remote.tsx:
import { MDXComponents } from "mdx/types";
import { MDXRemote, MDXRemoteProps } from "next-mdx-remote/rsc";
const components: MDXComponents = {
// Allows customizing built-in components, e.g. to add styling
h1: ({ children }) => <h1 className="text-red-500">{children}</h1>,
h2: ({ children }) => <h2 className="text-blue-500">{children}</h2>,
h3: ({ children }) => <h3 className="text-green-500">{children}</h3>,
};
Man erstellt hier quasi schnelle namenlose Komponenten und weist sie Properties im components
-Objekt zu. Das wird dann beim Compilen des MD bzw. MDX gelesen und die entsprechenden Komponenten werden 'ersetzt'. Dazu gibt man im zweiten Schritte das components
-Objekt an eine CustomMDX
-Komponente.
// src/components/mdx-remote.tsx:
export function CustomMDX(props: MDXRemoteProps) {
return (
<MDXRemote
{...props}
components={{ ...components, ...(props.components || {}) }}
options={{ parseFrontmatter: true }} // hides frontmatter on rendered MDX
/>
);
}
Im dritten Schritte importiert man die CustomMDX
-Komponente da wo man sein MDX rendern möchte und füttert sie mit dem bloßen, unveränderten Text-Inhalt seiner MDX-Datei.
// src/app/blog/[slug]/page.tsx
<article className="container prose mx-auto max-w-3xl py-6 dark:prose-invert">
<h1>{title}</h1>
<p className="flex justify-end space-x-1">
<span>by {author},</span>
<span>{publishDate}</span>
</p>
<CustomMDX source={fileContent} />
</article>
Und genau hier war das Problem. Die compileMDX
-Funktion von next-mdx-remote schnappt sich den Text-Inhalt einer MDX-Datei und wandelt ihn in Frontmatter und eine fertige React-Komponente um. Die React-Komponente ist aber schon fertig kompiliert und die CustomMDX
-Komponente hat jetzt hier keinen Einfluss mehr.
Darum hab ich jetzt die compileMDX
-Funktion nur genutzt um die Frontmatter vom Textinhalt zu trennen. Dann gebe ich den kompletten rohen Textinhalt (inklusive enthaltener Frontmatter) noch mal extra in die CustomMDX
-Komponente. Jetzt funzts. Aber irgendwie is dit scheiße. Fühlt sich irgendwie doppelt-gemoppelt an...
Naja, wahrscheinlich jammern auf hohem Niveau. Gerendert wird alles im Build-Prozess. Dürfte also keinerlei Performance- bzw. SEO-Einbußen in der Production verursachen.
Mission accomplished. 🚀