AI 对话里的流式 Markdown 为什么难:从不完整 Token 到增量渲染

在 AI 聊天界面里,Markdown 不是一次性得到的。模型会通过 SSE 或 WebSocket 持续返回 token,前端必须在内容还没结束时就开始渲染:标题可能只有半个字符,代码围栏可能还没有闭合,Mermaid 和数学公式也可能仍在生成。

这和渲染一篇已经完成的 Markdown 文档,是两个不同的问题。

传统 Markdown 渲染器遇到的几个问题

marked、markdown-it、react-markdown 等方案非常适合完整文档。把它们直接用于 token 流时,常见问题包括:

  • 不完整的代码围栏导致代码块在普通文本和代码之间反复跳动;
  • 表格、列表、链接等结构在每次更新时重新解释,页面出现抖动;
  • Mermaid、KaTeX 等重量级内容在尚未完成时就尝试渲染;
  • 长回答不断追加时,整棵渲染树反复更新,滚动位置也更难稳定。

Markstream 解决的是什么

Markstream 是专门面向 AI 对话流的 Markdown renderer family。Vue 3 项目可以直接安装:

bash 复制代码
pnpm add markstream-vue

最小使用方式:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import MarkdownRender from 'markstream-vue'
import 'markstream-vue/index.css'

const content = ref('')
const isDone = ref(false)

// 在真实项目中,这里可以替换成 SSE / WebSocket 的 token 回调
function onToken(token: string) {
  content.value += token
}
</script>

<template>
  <MarkdownRender mode="chat" :content="content" :final="isDone" />
</template>

它的重点不是替代所有 Markdown 工具,而是让"仍在变化的 Markdown"保持可读:

  • token 逐步到达时保持稳定的增量更新;
  • 支持 Mermaid、KaTeX 和语法高亮代码块;
  • 支持安全 HTML、SSR,以及较长的 AI 回答;
  • Vue、React、Svelte、Angular 和 Vue 2 有对应 sibling packages;
  • MIT License,可以直接集成到自己的 AI 聊天产品中。

什么时候不应该使用它

如果你的内容是已经完成的博客、文档或静态 Markdown 页面,marked、markdown-it、react-markdown 等成熟方案通常更简单。Markstream 适合的是模型仍在输出、用户已经开始阅读的那几秒钟。

如何选择

React 团队如果需要 react-markdown 风格的 drop-in API 和成熟插件生态,可以优先考虑 Streamdown 或其他成熟方案。Markstream 更适合需要跨 Vue / React / Svelte / Angular 保持相近流式行为,或者需要对重型块和长回答进行渲染控制的场景。

项目主页:markstream.simonhe.me/

GitHub:github.com/Simon-He95/...

Streamdown 对比:markstream.simonhe.me/compare/str...

Vue 快速开始:markstream.simonhe.me/frameworks/...

如果你正在做 AI 聊天、Copilot、知识库问答或任何 token 流式 UI,欢迎用一个真实的 SSE 响应试试,再根据实际体验决定是否采用。

相关推荐
u0111026758 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
雪芽蓝域zzs14 小时前
第 7 节:多边形点击弹窗 + 清空绘制按钮
vue.js
溪语流沙14 小时前
【Web全栈进阶】Composition API与组件通信:props深入、emit、插槽
前端·css·vue.js
顽疲17 小时前
Java vue 养老系统源码详解:入住核算单 live-check 缴费入账与预交金收据实践
java·vue.js·python·java 养老·springboot 养老·vue养老
志尊宝18 小时前
Vue3 零基础每日笔记(088·完结):从零到一——一个完整 Vue3 项目的成长复盘
前端·javascript·vue.js·笔记·ecmascript·#vue.js
桔筐18 小时前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
用户17335980753720 小时前
纯前端 PDF 按书签拆分避坑指南:拆分后章节对不上?
前端·javascript·vue.js
雪芽蓝域zzs21 小时前
Webstorm打开uniapp uvue文件报红处理方案
vue.js
撸串-研究生21 小时前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
志尊宝1 天前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js