@next/mdx入门

半兽人 发表于: 2025-06-19   最后更新时间: 2025-06-19 11:33:56  
{{totalSubscript}} 订阅, 9 游览

@next/mdx 插件的主要作用是 让 Next.js 支持 MDX 文件的导入和使用

什么是 @next/mdx

@next/mdx 是 Next.js 官方提供的一个插件,它结合了:

  • Markdown(.md)的简洁书写格式
  • JSX(React 组件)的功能

即:你可以在 .mdx 文件中写 Markdown 内容,也可以直接写 React 组件,比如:

# 这是一个标题

这是正文内容

<MyComponent />

主要作用

使用 require('@next/mdx') 的目的是:

.mdx 文件转译为可以被 Next.js 使用的 React 组件

常见的配置写法如下:

const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/
})

module.exports = withMDX({
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx']
})

配置解释

  • require('@next/mdx')({ extension })
    这是创建 MDX 插件实例,同时指定要处理 .mdx 文件。
  • withMDX(...)
    把这个插件应用到你的 Next.js 配置中。
  • pageExtensions
    告诉 Next.js,页面可以用 .mdx.md.tsx 等文件扩展名。

总结一句话:

require('@next/mdx') 的作用是让 Next.js 可以加载和渲染 .mdx 文件,把它们当作 React 组件来用。

完整例子

一、安装依赖

npm install @next/mdx @mdx-js/loader

二、配置 next.config.js

创建或修改 next.config.js

// next.config.js
const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/,
})

module.exports = withMDX({
  // 支持哪些扩展名作为页面
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
})

三、创建一个 .mdx 页面

pages 目录下创建一个 .mdx 页面,比如:

touch pages/about.mdx

内容示例:

# 关于我们

这是一个用 **MDX** 写的页面。

你还可以使用 React 组件,比如:

<CustomMessage name="张三" />

四、定义你用到的 React 组件

比如你用了 <CustomMessage />,就要在 _app.js.mdx 文件中导入:

方法一:直接在 .mdx 文件中引入

import CustomMessage from '../components/CustomMessage'

# 欢迎

<CustomMessage name="李四" />

方法二:在 _app.js 中提供(不推荐除非全局使用)

五、创建组件

mkdir components
touch components/CustomMessage.js

components/CustomMessage.js

export default function CustomMessage({ name }) {
  return <p>你好,{name},欢迎访问我们的网站!</p>
}

六、运行项目

npm run dev

访问 http://localhost:3000/about,你将看到:

关于我们
这是一个用 MDX 写的页面。
你好,张三,欢迎访问我们的网站!

高级玩法

一、带 Layout 的 .mdx 页面写法

目标:每个 .mdx 页面可以套用一个公共的布局(如统一导航、样式等)

1. 创建一个 Layout 组件(比如 components/Layout.js

// components/Layout.js
export default function Layout({ children }) {
  return (
    <div style={{ padding: 20, border: '1px solid #ddd' }}>
      <h1>网站公共标题</h1>
      <main>{children}</main>
    </div>
  );
}

2. 在 .mdx 页面中使用这个 Layout

---
layout: ../components/Layout
---

# 欢迎访问

这是一段内容。

上面这段 --- 是 YAML Frontmatter,用来指定 layout。

3. 在 pages/_app.js 中配置 MDX 的 layout 插件解析

需要用 next-mdx-enhanced 或自己写 loader,但更推荐直接使用 MDX Component Wrapping 方案:

新方法(MDX 文件中直接导入组件):

import Layout from '../components/Layout'

export default ({ children }) => <Layout>{children}</Layout>

# 标题

MDX 页面内容。

你也可以把 Layout 封装为默认导出的组件,.mdx 就变成一个真正的 React 组件。

二、多语言 MDX 页面结构(i18n)

Next.js 内置国际化(i18n)支持,你可以结合 .mdx 页面实现多语言切换。

1. 修改 next.config.js 增加 i18n

module.exports = {
  i18n: {
    locales: ['en', 'zh'],
    defaultLocale: 'zh',
  },
}

2. 按语言目录创建页面结构

pages/
  zh/
    about.mdx
  en/
    about.mdx

然后访问:

  • /zh/about:中文页面
  • /en/about:英文页面

三、动态加载 MDX 内容(next-mdx-remote

这种方式适合动态内容渲染,比如从 CMS、文件系统、数据库读取 .mdx 内容,然后渲染为 React 页面。

1. 安装依赖:

npm install next-mdx-remote

2. 页面示例(pages/blog/[slug].js):

import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
import fs from 'fs';
import path from 'path';

export default function BlogPost({ source }) {
  return (
    <article>
      <MDXRemote {...source} />
    </article>
  );
}

export async function getStaticPaths() {
  const files = fs.readdirSync('posts');
  const paths = files.map(file => ({
    params: { slug: file.replace(/\.mdx$/, '') },
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const filepath = path.join('posts', `${params.slug}.mdx`);
  const raw = fs.readFileSync(filepath, 'utf-8');
  const mdxSource = await serialize(raw); // 转换为 MDX 可渲染结构

  return { props: { source: mdxSource } };
}

3. 示例目录结构:

posts/
  hello.mdx
pages/
  blog/
    [slug].js

4. 访问效果:

访问 /blog/hello 就会动态渲染出 posts/hello.mdx 内容。

总结对比

方式 用途 是否支持动态内容 是否能嵌入组件
@next/mdx 静态页面,支持组件,配置简单
带 Layout 的 MDX 统一结构化渲染,适合文档站
多语言结构 多语言版本页面支持
next-mdx-remote 动态渲染,适合博客/CMS场景
更新于 2025-06-19
在线,1小时前登录

查看Next.js更多相关的文章或提一个关于Next.js的问题,也可以与我们一起分享文章