分享一个跨框架的 Markdown/MDX 解析器,帮你简化内容管理

24 阅读3分钟

各位好,

长期以来,在项目里管理 Markdown 真的挺让人头大的。第一个难题就是选库。

一方面,像 unified、remark 和 rehype 这种“乐高式”方案确实强大,但要配好整个 AST 流水线和插件系统,对我来说实在太复杂了,有点过度设计。 另一方面,@next/mdx 虽然不错,但太聚焦于页面渲染,而且在客户端跑不起来。

所以我以前更倾向于用 markdown-to-jsx 或 react-markdown。 它们的 DX(开发体验)好得多,客户端和服务端都能用,也更轻量。 但问题是它们原生不支持 HTML 或 MDX,结果最后还是得绕回插件的老路。再加上如果要做国际化(比如配合 i18next 或 next-intl),简直是场灾难。你得写一堆 if/else 来渲染对应的语言,包体积也跟着爆表。而且在处理 front-matter 和以前只支持 React 这几点上,坑也不少。

Screenshot 2026-01-29 at 5.59.24 PM.png

所以我决定为 intlayer 搞个新东西,一个开箱即用的方案。

顺便提一下,为了实现这个,我 fork 了 markdown-to-jsx v7.7.14(作者 quantizor),它是基于 simple-markdown v0.2.2(Khan Academy 出品)构建的。

我做这个解析器主要想实现几个目标:

  • 极致轻量
  • 框架无关(支持 React, Vue, Svelte, Angular, Solid, Preact)
  • 配置简单:拒绝疯狂的插件链
  • 同时支持 SSR 和客户端渲染
  • 可以在 Provider 级别配置,直接映射你的 UI 组件库
  • 以组件为中心,方便对应用的每个部分进行精细化渲染
  • 类型安全(自动获取 front-matter 类型和组件 Props 类型)
  • i18n 友好(针对多语言场景做了加载优化)
  • 使用 zod 校验 front-matter

来个 Demo:

你可以把它当成一个独立的工具库来用:

import { renderMarkdown } from "react-intlayer"; // Vue 用 vue-intlayer,Svelte 用 svelte-intlayer,以此类推

// 简单的渲染函数(返回的是 JSX/节点,不只是字符串)
renderMarkdown("### 我的标题", {
  components: { h3: (props) => <h3 className="text-xl" {...props} /> },
});

也可以通过组件和 Hook 来用:

import {
  MarkdownRenderer,
  MarkdownProvider,
  useMarkdownRenderer,
} from "react-intlayer";

// 组件写法
<MarkdownRenderer components={{ h3: MyCustomH3 }}>
  ### 我的标题
</MarkdownRenderer>;

<MarkdownProvider components={{ h3: MyCustomH3 }}>{children}</MarkdownProvider>;

// Hook 写法,配合 Provider Context
const render = useMarkdownRenderer();
return <div>{render("# 你好")}</div>;

如果配合 Intlayer 的内容声明一起用,那才是真的香,逻辑和内容完全解耦:

// ./myMarkdownContent.content.ts
import { md } from "intlayer";

export default {
  key: "my-content",
  content: md("## 这是我的多语言 MD"),

  // 加载本地文件系统内容
  //   content: md(readFileSync("./myMarkdown.md", "utf8")),

  // 加载远程内容
  //   content: md(fetch("https://api.example.com/content").then((res) => res.text())),
};

在组件里调用就像用普通变量一样,根本不需要手动解析:

const { myContent } = useIntlayer("my-content");

return (
  <div>
    {myContent} {/* 使用全局配置自动渲染 */}
    {/* 或者 */}
    {/* 临时覆盖组件配置 */}
    {myContent.use({
      h2: (props) => <h2 className="text-blue-500" {...props} />,
    })}
  </div>
);

这玩意儿创新在哪?

  • 真正的通用性:React、Vue、Svelte 用的都是同一套逻辑。
  • 轻量级类 MDX 编译器:在 Edge Runtime 和服务端跑起来飞快。
  • 零加载负担:无论内容是来自 fs 还是 fetch,都在构建时预加载好了。
  • 方便复用:可以轻松地在不同页面或文档里组织和复用小的 Markdown 片段。
  • 类型安全地解析 front-matter(类似 Contentlayer 以前干的事)。

适用于哪些场景?

  • 博客 / 文档 / 隐私政策 / 服务条款
  • 从后端获取的动态数据
  • 把页面内容外接到 Headless CMS
  • 直接加载 .md 文件

我做这个纯粹是因为受够了之前的那些方案。不知道大家有没有类似的痛点?或者你们现在在项目里是怎么处理 Markdown 的?

完整文档: intlayer.org/zh/doc/conc… 代码仓库: github.com/intlayer/in…