You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中mdx-components.js自定义组件无法渲染求助

自定义MDX组件无法渲染的解决方案

我尝试通过mdx-components.js向MDX文章传递自定义链接组件,但自定义组件未渲染。已确认文件被加载(移除文件时NextJS报错),但浏览器输出HTML显示原生<a>标签仍在,未被替换。相关代码如下:

1. mdx-components.js 文件

// my-blog/mdx-components.js

import UnderlineHoverLink from "./app/_components/Links/UnderlineHoverLink";

export function useMDXComponents(components) {
  return {
    a: ({ href, children }) => (
      <UnderlineHoverLink href={href}>{children}</UnderlineHoverLink>
    ),
    ...components,
  };
}

2. 渲染MDX的page.js页面

// my-blog/app/(routes)/posts/[slug]/page.js:

import { getPostBySlug } from "@/app/_lib/mdx";

const getPageContent = async (slug) => {
  const { meta, content } = await getPostBySlug(slug);
  return { meta, content };
};

export async function generateMetadata({ params }) {
  const { meta } = await getPageContent(params.slug);
  return { title: meta.title };
}

const Page = async ({ params }) => {
  console.log(params);
  const { content } = await getPageContent(params.slug);
  return content;
};

export default Page;

3. 读取MDX文件的工具代码

// my-blog/app/_lib/mdx/index.js

import fs from "fs";
import path from "path";
import { compileMDX } from "next-mdx-remote/rsc";

const rootDirectory = path.join(process.cwd(), "content/posts");

export const getPostBySlug = async (slug) => {
  const realSlug = slug.replace(/\.mdx$/, "");
  const filePath = path.join(rootDirectory, `${realSlug}.mdx`);

  const fileContent = fs.readFileSync(filePath, { encoding: "utf8" });

  const { frontmatter, content } = await compileMDX({
    source: fileContent,
    options: { parseFrontmatter: true },
  });

  return { meta: { ...frontmatter, slug: realSlug }, content };
};

核心问题原因

mdx-components.js 是Next.js内置MDX支持的配置方式,但你使用的是next-mdx-remote/rsc编译MDX,这种第三方编译方式不会自动读取mdx-components.js的配置,必须手动将自定义组件传递给compileMDX函数。

解决方案步骤

步骤1:修改MDX编译代码,手动传递组件

修改app/_lib/mdx/index.js,导入自定义组件并添加到compileMDX的components参数中:

// my-blog/app/_lib/mdx/index.js
import fs from "fs";
import path from "path";
import { compileMDX } from "next-mdx-remote/rsc";
// 导入你的自定义链接组件
import UnderlineHoverLink from "../../app/_components/Links/UnderlineHoverLink";

const rootDirectory = path.join(process.cwd(), "content/posts");

export const getPostBySlug = async (slug) => {
  const realSlug = slug.replace(/\.mdx$/, "");
  const filePath = path.join(rootDirectory, `${realSlug}.mdx`);

  const fileContent = fs.readFileSync(filePath, { encoding: "utf8" });

  const { frontmatter, content } = await compileMDX({
    source: fileContent,
    options: { parseFrontmatter: true },
    // 手动传递自定义组件映射
    components: {
      a: ({ href, children }) => (
        <UnderlineHoverLink href={href}>{children}</UnderlineHoverLink>
      ),
    },
  });

  return { meta: { ...frontmatter, slug: realSlug }, content };
};

步骤2:确保自定义组件符合RSC要求

如果UnderlineHoverLink包含客户端交互(如hover样式、点击事件),必须添加"use client"指令,否则在服务端组件中无法正常渲染:

// app/_components/Links/UnderlineHoverLink.js
"use client";

import Link from "next/link";

export default function UnderlineHoverLink({ href, children }) {
  return (
    <Link 
      href={href} 
      className="underline decoration-2 decoration-blue-500 hover:decoration-red-500 transition-colors"
    >
      {children}
    </Link>
  );
}

步骤3:(可选)复用组件配置(同时支持内置MDX和remote MDX)

如果需要同时支持Next.js内置MDX和next-mdx-remote,可以将组件配置抽离成单独文件,在两个地方复用:

  1. 创建app/_lib/mdx/custom-components.js:
import UnderlineHoverLink from "../../app/_components/Links/UnderlineHoverLink";

export const customMDXComponents = {
  a: ({ href, children }) => (
    <UnderlineHoverLink href={href}>{children}</UnderlineHoverLink>
  ),
};
  1. 修改mdx-components.js:
import { customMDXComponents } from "./app/_lib/mdx/custom-components";

export function useMDXComponents(components) {
  return {
    ...customMDXComponents,
    ...components,
  };
}
  1. 修改app/_lib/mdx/index.js:
import { customMDXComponents } from "./custom-components";

// ... 其他代码
const { frontmatter, content } = await compileMDX({
  source: fileContent,
  options: { parseFrontmatter: true },
  components: customMDXComponents,
});

内容的提问来源于stack exchange,提问作者Nicole Orchard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:41:25