MdBin 升级:从自定义 Markdown 管道到 Streamdown

发布: (2026年1月17日 GMT+8 11:08)
8 min read
原文: Dev.to

Source: Dev.to

旧的设置:它能工作,但

我最初的实现相当稳固。我使用 markdown-it-async 搭配 @shikijs/markdown-it 来进行语法高亮:

import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async'
import MarkdownItAsync from 'markdown-it-async'
import { codeToHtml } from 'shiki'

const md = MarkdownItAsync({
  html: true,
  xhtmlOut: true,
  linkify: true,
  typographer: true,
  breaks: true,
})

md.use(
  fromAsyncCodeToHtml(codeToHtml, {
    themes: {
      light: 'github-light',
      dark: 'github-dark',
    },
    defaultColor: false,
    cssVariablePrefix: '--shiki-',
  })
)

export async function renderMarkdown(content: string): Promise {
  const html = await md.renderAsync(content)
  return html
}

然后在我的页面组件中,我使用经典的 dangerouslySetInnerHTML 渲染结果:

缺点

  • 手动安全处理dangerouslySetInnerHTML 正如其名,使用时需格外小心。
  • 缺乏内置控制 — 复制按钮、下载功能等都需要自己实现。
  • Mermaid 成了噩梦 — 服务端渲染时往往不可靠。
  • 包体积膨胀 — 每新增一种语言的高亮都会增加体积。
  • 块级处理不完整 — 格式错误的 Markdown 可能导致整个渲染失败。

进入 Streamdown

当我发现 Streamdown 时,我最初把它否掉了。“它是用于 AI 流式传输的,”我想。“MdBin 渲染的是静态内容 SSR。”

但随后我仔细查看了功能集:

  • 🎯 代码语法高亮,使用 Shiki(我已经在使用的)
  • 📈 Mermaid 图表,真正支持 SSR
  • 🛡️ 安全‑优先,配合 rehype-harden
  • 📊 GitHub 风格的 Markdown 开箱即用
  • 🔢 数学渲染,通过 KaTeX
  • 内置控制,包括复制、下载、全屏

这正是一个 Markdown‑分享工具所需要的。

迁移:出乎意料的轻松

下面是新实现的样子:

import { Streamdown } from 'streamdown'

export default async function PastePage({ params }) {
  const { id } = await params
  const { decompressedContent, createdAt } = await cachedGetPaste(id)

  return (
    <Streamdown mode="static">
      {decompressedContent}
    </Streamdown>
  )
}

就这么简单。没有单独的渲染函数,没有 dangerouslySetInnerHTML,也没有手动的安全清理。

Tailwind 的配置只需在 globals.css 中添加一行:

@source "../../node_modules/streamdown/dist/index.js";

为什么 v2.0.0 是游戏规则改变者

时机再好不过了。Streamdown 刚刚发布了 v2.0.0,带来了巨大的改进:

🚀 通过 CDN 将包体积降低 98 %

之前,打包所有 Shiki 语言语法和主题会让构建体积膨胀。现在,语言特定的高亮和 KaTeX CSS 会按需从 CDN 加载。你的构建保持精简,用户只会获取他们需要的资源。

📈 Mermaid SSR 终于可以用了

Markdown 中的 Mermaid 图表非常实用——流程图、时序图、架构文档——但 SSR 渲染一直有问题。现在它可以完美工作,并且采用基于视口的懒加载,防止在页面中出现多个图表时导致卡顿。

🛡️ 增强的安全性

rehype-harden + rehype-sanitize 意味着我不必担心恶意 Markdown 带来的 XSS 攻击。组件会自动处理消毒。

✨ 内置的用户体验优化

所有我本来得自己实现的控件?现在已内置:

  • 代码块 – 复制按钮,语言指示
  • 表格 – 下载为 CSV
  • Mermaid – 下载为 PNG,复制 SVG,全屏查看并支持平移/缩放

我获得的

功能之前之后
安全手动使用 dangerouslySetInnerHTML内置 rehype-harden
代码复制自定义 CopyButton 组件✅ 内置
Mermaid SSR❌ 损坏✅ 可用
表格下载❌ 未实现✅ 内置
数学渲染❌ 未实现✅ 内置 KaTeX
包大小随着每种语言的增加而增长按需 CDN 加载
不完整的 Markdown可能导致渲染错误优雅处理

“流式”部分

你可能会好奇:“为什么要为静态内容使用流式优化的组件?”答案很简单——Streamdown 的流式模式提供了渐进式渲染。Markdown 会在解析后即时流向 DOM,这意味着:

  • 更快的首次有内容绘制时间(尤其是对大型文章)。
  • 在处理繁重的图表或代码块时,UI 仍保持响应。
  • 对静态 SSR 和实时 AI 生成的流都同样适用,为未来功能提供灵活性。

简而言之,我获得了更简洁的代码库、更好的安全性、显著更小的包体积以及更丰富的用户体验——几乎无需迁移工作量。

Cover image for MdBin Levels Up: From Custom Markdown Pipeline to Streamdown

“用于静态内容的 ed 库?”

公平的问题。mode="streaming"isAnimating={false} 属性告诉 Streamdown 这是预渲染的内容——没有打字效果,也没有逐步显示。但其他所有好处仍然适用:

  • parseIncompleteMarkdown – 处理用户粘贴格式错误的 markdown(未闭合的代码块、不完整的表格)等边缘情况。它不会崩溃或显示乱码,而是优雅地渲染。
  • Memoized rendering – 即使没有流式处理,性能优化仍有助于重新渲染。

向 Vercel 团队致敬

The Streamdown team has done an incredible job packaging what could have been a complex, multi‑library setup into a single, well‑designed component. It powers their AI Elements Message component, but it’s genuinely useful for any markdown‑rendering use case.

  • 文档很完善。
  • 默认设置合理。
  • 它就是能用。

试一试

前往 并粘贴一些 markdown。尝试:

  • 代码块(任意语言)——注意复制按钮和语言徽章。
  • Mermaid 图表——它们现在真的可以渲染!尝试全屏 + 平移/缩放。
  • 表格——查看下载按钮。
  • 数学公式——LaTeX 直接可用。

快速 Mermaid 示例,复制粘贴

graph TD
    A[Paste Markdown] --> B[Streamdown Renders]
    B --> C{What type?}
    C -->|Code| D[Shiki Highlighting]
    C -->|Diagram| E[Mermaid SVG]
    C -->|Math| F[KaTeX Render]
    D --> G[Beautiful Output]
    E --> G
    F --> G
  • 进入全屏模式
  • 退出全屏模式

接下来

随着渲染层现在由 Streamdown 负责,我可以专注于用户真正想要的功能:

  • 过期选项 – 1 小时、1 天、1 周或永久。
  • 密码保护 – 用于敏感内容。
  • 编辑链接 – 在不创建新粘贴的情况下更新已有粘贴。
  • 自定义主题 – 超越浅色/深色模式。

基础已经稳固。现在是构建的时候了。

TL;DR: 将 MdBin 从 markdown-it + Shiki 迁移到 Vercel 的 Streamdown。获得了内置代码复制、Mermaid 渲染(真正支持 SSR!)、数学支持、增强的安全性,以及体积缩小 98 % 的打包——全部来自一个组件。Vercel 团队这次表现堪称完美。

查看升级内容于 以及 Streamdown 仓库

Back to Blog

相关文章

阅读更多 »

关于此文档基础设施

文档结构 所有文档均以 Markdown 文件形式存放在 GitHub 仓库的 ./documentation 目录中。这是唯一可信来源。

前四个

关于 Raku Resolutions 的后续跟进 https://dev.to/lizmat/raku-resolutions-17g7 第一次会议已在建议的时间和日期举行:2026年1月17日 19:00 UT。

LuxDev Markdown 语言类

如何使用 markdown 语言编写标题——一个 # 符号将文本设为标题,两个 # 符号将文本设为副标题,三个 # 符号将其设为子章节……