In diesem Artikel beschreibe ich, wie ich einen Blogbereich zu unserer bestehenden Next.js-Homepage hinzugefügt habe. Dabei nutze ich Markdown-Dateien (MDX) zur Verwaltung der Blogposts. Dies erlaubt eine einfache und flexible Art, Inhalte zu erstellen und zu bearbeiten.
Um MDX-Dateien in unsere Next.js-Anwendung zu integrieren, habe ich die folgenden Pakete verwendet:
In der next-config.mjs habe ich withMDX hinzugefügt, um die MDX-Integration zu konfigurieren.
code-snippet.ts
import createMDX from '@next/mdx' /** * @type {import('next').NextConfig} */ const nextConfig = { ... pageExtensions: ['mdx', 'md', 'tsx', 'ts'], ... }; const withMDX = createMDX({ // Add markdown plugins here, as desired }); export default withMDX(nextConfig);
Zuerst habe ich eine Datei mdx-component.tsx erstellt, um benutzerdefinierte MDX-Komponenten zu definieren.
code-snippet.ts
import type { MDXComponents } from "mdx/types"; export function useMDXComponents(components: MDXComponents): MDXComponents { return { ...components, }; }
In der Datei mdxUtils.ts habe ich Funktionen zum Verwalten der MDX-Dateien erstellt. Diese Funktionen helfen dabei, den Pfad zu den Posts zu bekommen und alle MDX-Dateien im Verzeichnis posts zu finden.
code-snippet.ts
/** * Useful when you want to get the path to a specific file */ export const POSTS_PATH = path.join(process.cwd(), "posts"); /** * The list of all mdx files inside the POSTS_PATH directory */ export const postFilePaths = fs .readdirSync(POSTS_PATH) // Only include md(x) files .filter((path) => /\.mdx?$/.test(path));
In der Datei app/posts/page.tsx habe ich eine Übersichtsseite erstellt, die alle gefundenen Markdown-Artikel als Karten auflistet und zum Weiterlesen verlinkt.
code-snippet.ts
import { postFilePaths, POSTS_PATH } from "../../utils/mdxUtils.ts"; interface Post { filePath: string; data: { title: string; description: string; image: string; author: string; date: string; }; content: string; } function getData(): { posts: Post[] } { const posts = postFilePaths.map((filePath) => { const source = fs.readFileSync(path.join(POSTS_PATH, filePath)); const { content, data } = matter(source); return { content, data, filePath, } as Post; }); return { posts }; } const Posts: React.FC = () => { const { posts } = getData(); return ( <> ... <Box sx={{ display: "grid", gap: 4, gridTemplateColumns: { md: "1fr 1fr 1fr", sm: "1fr 1fr", xs: "1fr", }, }} > {posts .sort( (a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime(), ) .map((post) => ( <Link key={post.filePath} as={`/posts/${post.filePath.replace(/\.mdx?$/, "")}`} href={`/posts/[slug]`} style={{ textDecoration: "none", }} > ... </Link> ))} </Box> ... </> ); }; export default Posts;
Schließlich wird jeder Blogpost über die Datei app/posts/[slug]/page.tsx gerendert.
code-snippet.ts
import { MDXRemote } from "next-mdx-remote/rsc"; import { POSTS_PATH } from "../../../utils/mdxUtils.ts"; import matter from "gray-matter"; import type { MDXRemoteProps } from "next-mdx-remote/rsc"; const components: MDXRemoteProps["components"] = { h1: (props) => <Typography variant="h1">{props.children}</Typography>, h2: (props) => <Typography variant="h2">{props.children}</Typography>, h3: (props) => <Typography variant="h3">{props.children}</Typography>, h4: (props) => <Typography variant="h4">{props.children}</Typography>, p: (props) => ( <Typography variant="body1" gutterBottom> {props.children} </Typography> ), }; const Posts: React.FC<{ params: { slug: string } }> = ({ params: { slug }, }) => { const postFilePath = path.join(POSTS_PATH, `${slug}.mdx`); const source = fs.readFileSync(postFilePath); const { data } = matter(source); return ( <> <Hero title={data.title} subtitle={data.description} image={data.image} /> <Block> <MDXRemote components={components} source={source} options={{ parseFrontmatter: true, }} /> </Block> </> ); }; export default Posts;
Mit dieser Implementierung können wir neue Blogposts hinzufügen und verwalten, indem wir einfach neue MDX-Dateien im posts Verzeichnis erstellen. Das System ermöglicht es uns, die Inhalte klar strukturiert und ansprechend zu präsentieren. Next.js bietet dabei die notwendige Flexibilität und Leistung, um auch größere Mengen an Inhalten effizient zu verwalten.