Markdown und MDX
Markdown ist eine leichtgewichtige Auszeichnungssprache zur Textformatierung. Sie ermöglicht das Schreiben mit einfacher Textsyntax und die Konvertierung in strukturell valides HTML. Es wird häufig für das Verfassen von Inhalten auf Websites und Blogs verwendet.
Sie schreiben...
I **love** using [Next.js](https://nextjs.org/)
Ausgabe:
<p>I <strong>love</strong> using <a href="https://nextjs.org/">Next.js</a></p>
MDX ist eine Erweiterung von Markdown, die es Ihnen ermöglicht, JSX direkt in Ihren Markdown-Dateien zu verwenden. Es ist eine leistungsstarke Methode, um dynamische Interaktivität hinzuzufügen und React-Komponenten in Ihre Inhalte einzubetten.
Next.js unterstützt sowohl lokale MDX-Inhalte innerhalb Ihrer Anwendung als auch remote MDX-Dateien, die dynamisch auf dem Server abgerufen werden. Das Next.js-Plugin übernimmt die Transformation von Markdown und React-Komponenten in HTML, einschließlich der Unterstützung für die Verwendung in Server Components (Standard im App Router).
@next/mdx
Das @next/mdx
-Paket wird verwendet, um Next.js für die Verarbeitung von Markdown und MDX zu konfigurieren. Es bezieht Daten aus lokalen Dateien, sodass Sie Seiten mit der Erweiterung .mdx
direkt in Ihrem /pages
- oder /app
-Verzeichnis erstellen können.
Gehen wir durch, wie Sie MDX mit Next.js konfigurieren und verwenden.
Erste Schritte
Installieren Sie die benötigten Pakete, um MDX zu rendern:
npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
Erstellen Sie eine Datei mdx-components.tsx
im Stammverzeichnis Ihrer Anwendung (src/
oder das übergeordnete Verzeichnis von app/
):
Gut zu wissen:
mdx-components.tsx
ist erforderlich, um MDX mit dem App Router zu verwenden, und funktioniert nicht ohne sie.
import type { MDXComponents } from 'mdx/types'
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
}
}
export function useMDXComponents(components) {
return {
...components,
}
}
Aktualisieren Sie die Datei next.config.js
im Stammverzeichnis Ihres Projekts, um die Verwendung von MDX zu konfigurieren:
const withMDX = require('@next/mdx')()
/** @type {import('next').NextConfig} */
const nextConfig = {
// Konfigurieren Sie `pageExtensions`, um MDX-Dateien einzubeziehen
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
// Optional: Fügen Sie weitere Next.js-Konfigurationen hinzu
}
module.exports = withMDX(nextConfig)
Erstellen Sie dann eine neue MDX-Seite im /app
-Verzeichnis:
your-project
├── app
│ └── my-mdx-page
│ └── page.mdx
└── package.json
Jetzt können Sie Markdown verwenden und React-Komponenten direkt in Ihrer MDX-Seite importieren:
import { MyComponent } from 'my-components'
# Willkommen auf meiner MDX-Seite!
Dies ist ein **fetter** und _kursiver_ Text.
Dies ist eine Liste in Markdown:
- Eins
- Zwei
- Drei
Sehen Sie sich meine React-Komponente an:
<MyComponent />
Wenn Sie zur Route /my-mdx-page
navigieren, sollte Ihr gerenderter MDX-Inhalt angezeigt werden.
Remote MDX
Wenn sich Ihre Markdown- oder MDX-Dateien oder -Inhalte an einem anderen Ort befinden, können Sie sie dynamisch auf dem Server abrufen. Dies ist nützlich für Inhalte, die in einem separaten lokalen Ordner, einem CMS, einer Datenbank oder anderswo gespeichert sind. Ein beliebiges Community-Paket für diesen Anwendungsfall ist next-mdx-remote
.
Gut zu wissen: Bitte gehen Sie vorsichtig vor. MDX wird in JavaScript kompiliert und auf dem Server ausgeführt. Sie sollten MDX-Inhalte nur aus einer vertrauenswürdigen Quelle abrufen, da dies sonst zu Remote-Code-Ausführung (RCE) führen kann.
Das folgende Beispiel verwendet next-mdx-remote
:
import { MDXRemote } from 'next-mdx-remote/rsc'
export default async function RemoteMdxPage() {
// MDX-Text - kann aus einer lokalen Datei, Datenbank, CMS, Fetch usw. stammen...
const res = await fetch('https://...')
const markdown = await res.text()
return <MDXRemote source={markdown} />
}
import { MDXRemote } from 'next-mdx-remote/rsc'
export default async function RemoteMdxPage() {
// MDX-Text - kann aus einer lokalen Datei, Datenbank, CMS, Fetch usw. stammen...
const res = await fetch('https://...')
const markdown = await res.text()
return <MDXRemote source={markdown} />
}
Wenn Sie zur Route /my-mdx-page-remote
navigieren, sollte Ihr gerenderter MDX-Inhalt angezeigt werden.
Layouts
Um ein Layout über mehrere MDX-Seiten hinweg zu teilen, können Sie die integrierte Layout-Unterstützung mit dem App Router verwenden.
export default function MdxLayout({ children }: { children: React.ReactNode }) {
// Erstellen Sie hier gemeinsame Layouts oder Stile
return <div style={{ color: 'blue' }}>{children}</div>
}
export default function MdxLayout({ children }) {
// Erstellen Sie hier gemeinsame Layouts oder Stile
return <div style={{ color: 'blue' }}>{children}</div>
}
Remark- und Rehype-Plugins
Sie können optional remark
- und rehype
-Plugins bereitstellen, um den MDX-Inhalt zu transformieren.
Beispielsweise können Sie remark-gfm
verwenden, um GitHub Flavored Markdown zu unterstützen.
Da das remark
- und rehype
-Ökosystem nur ESM unterstützt, müssen Sie next.config.mjs
als Konfigurationsdatei verwenden.
import remarkGfm from 'remark-gfm'
import createMDX from '@next/mdx'
/** @type {import('next').NextConfig} */
const nextConfig = {
// Konfigurieren Sie `pageExtensions`, um MDX-Dateien einzubeziehen
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
// Optional: Fügen Sie weitere Next.js-Konfigurationen hinzu
}
const withMDX = createMDX({
// Fügen Sie hier gewünschte Markdown-Plugins hinzu
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
},
})
// Kombinieren Sie MDX- und Next.js-Konfiguration
export default withMDX(nextConfig)
Frontmatter
Frontmatter ist eine YAML-ähnliche Schlüssel/Wert-Paarung, die verwendet werden kann, um Metadaten über eine Seite zu speichern. @next/mdx
unterstützt Frontmatter nicht standardmäßig, obwohl es viele Lösungen gibt, um Frontmatter zu Ihren MDX-Inhalten hinzuzufügen, wie z.B.:
Um Seitenmetadaten mit @next/mdx
abzurufen, können Sie ein Metadaten-Objekt aus der .mdx
-Datei exportieren:
export const metadata = {
author: 'John Doe',
}
# Meine MDX-Seite
Benutzerdefinierte Elemente
Ein angenehmer Aspekt der Verwendung von Markdown ist, dass es auf native HTML
-Elemente abgebildet wird, was das Schreiben schnell und intuitiv macht:
Dies ist eine Liste in Markdown:
- Eins
- Zwei
- Drei
Das obige Beispiel generiert das folgende HTML
:
<p>Dies ist eine Liste in Markdown:</p>
<ul>
<li>Eins</li>
<li>Zwei</li>
<li>Drei</li>
</ul>
Wenn Sie Ihre eigenen Elemente für ein individuelles Erscheinungsbild Ihrer Website oder Anwendung gestalten möchten, können Sie Shortcodes verwenden. Dies sind Ihre eigenen benutzerdefinierten Komponenten, die auf HTML
-Elemente abgebildet werden.
Öffnen Sie dazu die Datei mdx-components.tsx
im Stammverzeichnis Ihrer Anwendung und fügen Sie benutzerdefinierte Elemente hinzu:
import type { MDXComponents } from 'mdx/types'
import Image, { ImageProps } from 'next/image'
// Diese Datei ermöglicht es Ihnen, benutzerdefinierte React-Komponenten
// für die Verwendung in MDX-Dateien bereitzustellen. Sie können jede
// React-Komponente importieren und verwenden, einschließlich Inline-Stilen,
// Komponenten aus anderen Bibliotheken usw.
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
// Ermöglicht die Anpassung integrierter Komponenten, z.B. für Styling.
h1: ({ children }) => <h1 style={{ fontSize: '100px' }}>{children}</h1>,
img: (props) => (
<Image
sizes="100vw"
style={{ width: '100%', height: 'auto' }}
{...(props as ImageProps)}
/>
),
...components,
}
}
import Image from 'next/image'
// Diese Datei ermöglicht es Ihnen, benutzerdefinierte React-Komponenten
// für die Verwendung in MDX-Dateien bereitzustellen. Sie können jede
// React-Komponente importieren und verwenden, einschließlich Inline-Stilen,
// Komponenten aus anderen Bibliotheken usw.
export function useMDXComponents(components) {
return {
// Ermöglicht die Anpassung integrierter Komponenten, z.B. für Styling.
h1: ({ children }) => <h1 style={{ fontSize: '100px' }}>{children}</h1>,
img: (props) => (
<Image
sizes="100vw"
style={{ width: '100%', height: 'auto' }}
{...props}
/>
),
...components,
}
}
Vertiefung: Wie wird Markdown in HTML transformiert?
React versteht Markdown nicht nativ. Der Markdown-Text muss zunächst in HTML transformiert werden. Dies kann mit remark
und rehype
erreicht werden.
remark
ist ein Ökosystem von Tools rund um Markdown. rehype
ist dasselbe, aber für HTML. Der folgende Codeausschnitt transformiert beispielsweise Markdown in HTML:
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeSanitize from 'rehype-sanitize'
import rehypeStringify from 'rehype-stringify'
main()
async function main() {
const file = await unified()
.use(remarkParse) // In Markdown-AST konvertieren
.use(remarkRehype) // In HTML-AST transformieren
.use(rehypeSanitize) // HTML-Eingabe bereinigen
.use(rehypeStringify) // AST in serialisiertes HTML konvertieren
.process('Hello, Next.js!')
console.log(String(file)) // <p>Hello, Next.js!</p>
}
Das remark
- und rehype
-Ökosystem enthält Plugins für Syntax-Hervorhebung, verlinkte Überschriften, Generierung eines Inhaltsverzeichnisses und mehr.
Wenn Sie @next/mdx
wie oben gezeigt verwenden, müssen Sie remark
oder rehype
nicht direkt verwenden, da dies für Sie erledigt wird. Wir beschreiben es hier, um ein tieferes Verständnis dafür zu vermitteln, was das @next/mdx
-Paket im Hintergrund tut.
Verwendung des Rust-basierten MDX-Compilers (Experimentell)
Next.js unterstützt einen neuen MDX-Compiler, der in Rust geschrieben wurde. Dieser Compiler ist noch experimentell und nicht für den Produktionseinsatz empfohlen. Um den neuen Compiler zu verwenden, müssen Sie next.config.js
konfigurieren, wenn Sie sie an withMDX
übergeben:
module.exports = withMDX({
experimental: {
mdxRs: true,
},
})