在Next.js渲染Markdown竟然如此简单
Next.js 作为一款开箱即用的 React 框架,因其优秀的服务器渲染能力和灵活的配置方式,已经吸引了大量的开发者。同时,Markdown 作为一种轻量级的标记语言,以其简洁的语法和强大的功能,已经成为了写作的首选工具。那么,如何在 Next.js 中渲染 Markdown 呢?这可能会让一些开发者感到困惑,但其实这个过程比你想象的要简单得多。在这篇文章中,我将会详细地解释如何在 Next.js 中渲染 Markdown,希望能为那些正在寻找解决方案的开发者提供一些参考和帮助。
什么是 Markdown
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换为有效的 HTML 文档。它可以用来制作说明文档、网页内容、电子书等。它的设计目标是易读性和易写性,以及尽可能的兼容性。Markdown 的语法由一些简单的符号组成,如井号(#)、星号(*)和破折号(-)。
MDX 则是一种扩展 Markdown 的语言,它允许你在 Markdown 文档中直接编写 JSX,并通过组件来导入和使用。这意味着你可以在 Markdown 中使用 React 组件,或者在 JSX 中使用 Markdown。MDX 非常适合用于创建复杂的交互式文档、幻灯片、博客等。
开始
项目基于 create-next-app 搭建,安装了 TailwindCSS。
PS E:\> pnpm create create-next-app@latest
√ What is your project named? ... next-mdx
√ Would you like to use TypeScript? ... Yes
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... Yes
√ Would you like to use `src/` directory? ... No
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@/*)? ... No
安装渲染 MDX 所需要的包:
pnpm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
在根目录创建一个 mdx-components.tsx
文件:
import type { MDXComponents } from 'mdx/types'
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
}
}
这里解构的 components
可以是 HTML 标签,也可以是我们的 jsx/tsx 文件,比如我新建 components/button.tsx
文件:
const Button = ({ children }: { children: React.ReactNode }) => {
return (
<button className="test-xs px-4 py-2 bg-zinc-950 text-white rounded-md">
{children}
</button>
);
};
export default Button;
修改 mdx-components.tsx
文件:
import type { MDXComponents } from "mdx/types";
import Button from "@/components/button";
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
h1: (props) => <h1 className="text-3xl font-bold">{props.children}</h1>,
Button,
};
}
上面代码给 h1
标签添加了两个 class:text-3xl font-bold
设置一级标题字体大小与加粗,并且导入了 Button 组件。
修改根目录中的 next.config.js
文件:
const withMDX = require("@next/mdx")();
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
};
module.exports = withMDX(nextConfig);
然后就可以在项目中愉快的渲染 .mdx
文件了。
新建 src/mdx/page.mdx
:
export const metadata = {
title: 'mdx'
}
# mdx-remote
- 1
- 2
- 3
<Button>button</Button>
由于我们前面在 mdx-components.tsx
中添加了 Button 组件,于是可以直接在 mdx 中使用。
export const metadata
用于设置页面元数据,这些元数据对于SEO(搜索引擎优化)非常重要。
访问 /mdx
页面,你将会看到以下页面,并且网页的标题也被修改为了 mdx
:
Remote MDX
如果 Markdown 或 MDX 文件或内容位于其他位置,比如本地文件夹、远程 URL、数据库等,则需要在服务器上动态获取它。
有两个常用的库,一个是 next-mdx-remote
一个是 contentlayer
,接下来我将演示如何在 Next.js 中使用 next-mdx-remote
来渲染 mdx
文件。
安装 next-mdx-remote
:
pnpm install next-mdx-remote
新建 components/mdx-components.tsx
文件:
"use client";
import { MDXRemote, MDXRemoteProps } from "next-mdx-remote";
import Button from "./button";
export default function Mdx(props: MDXRemoteProps) {
return (
<MDXRemote
{...props}
components={{
h1: (props) => {
return <h1 className="text-3xl font-bold">{props.children}</h1>;
},
Button,
}}
/>
);
}
创建文件 app/[slug]/page.tsx
文件:
import { MDXRemote } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import fs from "fs";
import Mdx from "@/components/mdx-components";
import { notFound } from "next/navigation";
interface PostProps {
params: {
slug: string;
};
}
const PostsPage = async ({ params: { slug } }: PostProps) => {
try {
const postFile = fs.readFileSync(`posts/${slug}.mdx`);
const source = await serialize(postFile, { parseFrontmatter: true });
return (
<div>
<Mdx {...source} />
</div>
);
} catch {
notFound();
}
};
export default PostsPage;
async function getPostBySlug(slug: string) {
const postFile = fs.readFileSync(`posts/${slug}.mdx`);
const source = await serialize(postFile, { parseFrontmatter: true });
return source;
}
export async function generateMetadata({ params }: PostProps) {
const { frontmatter } = await getPostBySlug(params.slug);
return frontmatter;
}
- 读取指定的MDX文件:通过网页的 URL 参数,使用 Node.js 的文件系统模块 fs 来读取 MDX 文件。
- 解析 MDX 文件:使用
serialize
函数将读取到的 MDX 文件内容进行解析和转化,可以将 MDX 格式的文件转化为可以在 React 中直接使用的 JSX 格式。 - 处理错误:如果在读取或解析文件的过程中出现错误(例如文件不存在),则会调用
notFound
函数进入 404 页面。 - 渲染 MDX 内容:使用自定义的
Mdx
组件将解析后的 MDX 内容进行渲染,展示在页面上。 - 提取MDX文件的元数据:
generateMetadata
函数会提取 MDX 文件的 frontmatter 元数据,这些元数据通常用于存储一些关于文档的信息,如作者、创建日期等。 - 将
generateMetadata
函数导出,便可以在页面中渲染元数据。
新建 posts/mdx-remote.mdx
文件:
---
title: mdx-remote
description: description
data: 2023-12-19
authro: 远小帅
---
# mdx-remote
- 1
- 2
- 3
<Button>button</Button>
在文件开头我使用了三个破折号包括了一段数据,这被称为 Frontmatter,采用 YAML
格式,用来描述文档的元数据。
此时访问 /mdx-remote
页面,便可以看到和刚才图片相同的页面。
总结
在这篇文章中,我详细介绍了如何在 Next.js 中渲染 Markdown 和 MDX 文件。希望这篇文章能够帮助你更好地理解和使用 Markdown 和 MDX 在 Next.js 中的应用,为你的开发工作带来便利。
下一篇文章我将开发一个具有 SEO 优化的博客实战项目,使用 MDX 渲染,有感兴趣的小伙伴可以关注一下。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!