description: 在 Nuxt 3 SSR 中使用 markstream-vue,获得服务端 HTML、稳定 fallback,以及重节点的客户端增强。
Nuxt 3 SSR 用法示例
For the English version, see nuxt-ssr.md.
markstream-vue 现在可以直接在 Nuxt SSR 中产出服务端 HTML。为了“能跑”而把整个 <MarkdownRender> 包进 <ClientOnly>,已经不是默认推荐做法。
当前的 SSR 模型是:
- 普通 markdown、HTML、链接、表格、脚注、图片会直接在服务端渲染。
- 代码块会先输出稳定的服务端
<pre><code>fallback,再在客户端增强成 Monaco。 - 数学公式在提供同步 KaTeX loader 时,可以直接在服务端输出真正的 KaTeX HTML。
- Mermaid、D2、Infographic 会先输出可读的 SSR fallback,再在客户端增强。
- scoped 自定义组件覆盖、自定义 node type、以及
customHtmlTags也都能参与服务端渲染。
最小 SSR 页面
<script setup lang="ts">
import MarkdownRender from 'markstream-vue'
import { ref } from 'vue'
const markdown = ref(`
# 来自 Nuxt SSR 的问候
行内公式:$E = mc^2$
\`\`\`ts
export const greet = (name: string) => \`hello \${name}\`
\`\`\`
\`\`\`mermaid
graph TD
SSR --> Hydration
\`\`\`
`.trim())
</script>
<template>
<MarkdownRender :content="markdown" :final="true" />
</template>这样首包就已经有服务端 HTML;重节点仍然会在 hydration 后增强,但不会先给你一个空壳。
服务端渲染数学公式
如果你希望 SSR 响应里直接带 KaTeX HTML,可以在 Nuxt 应用里注册同步 loader:
import katex from 'katex'
import { enableKatex } from 'markstream-vue'
enableKatex(() => katex)如果没有这个 loader,数学公式也仍然是 SSR-safe,只是会稳定回退成可读原文。
预解析 nodes 与自定义组件
除了直接传 content,你也可以在 SSR 中传 nodes,或者配合 scoped custom components / trusted custom tags 一起使用。
import { setCustomComponents } from 'markstream-vue'
import { defineComponent, h } from 'vue'
setCustomComponents('docs-ssr', {
thinking: defineComponent({
props: {
node: { type: Object, required: true },
},
setup(props) {
return () => h('aside', { 'data-ssr-thinking': '1' }, String((props.node as any).content ?? ''))
},
}),
})<template>
<MarkdownRender
custom-id="docs-ssr"
content="<thinking>服务端自定义标签</thinking>"
:custom-html-tags="['thinking']"
:final="true"
/>
</template>如果你的服务端已经拿到了 AST,优先用 nodes + final,这样可以避免浏览器端重复解析,SSR 输出也更可控。
什么时候还需要 <ClientOnly>
通常不是给渲染器本身用的。
只有当你自己的页面逻辑本身依赖浏览器 API,或者你明确想让一整块区域跳过 SSR 时,才需要 <ClientOnly>。
Nuxt playground
仓库里已经提供了完整的 Nuxt playground,路径是 playground-nuxt/:
pnpm install
pnpm play:nuxt专门的 SSR 验证路由是:
/ssr-lab
这个页面里有固定矩阵,用来覆盖:
- 基础 markdown + HTML 的 SSR
- 重节点的 SSR fallback
- hydration 后的增强路径
- 显式禁用增强时的稳定 fallback
- 自定义标签与 scoped override 的验证
SSR 验收命令
Nuxt SSR 的验收 e2e 命令是:
pnpm test:e2e:nuxt-ssr它会同时验证:
nuxt devnuxt build && nuxt preview
每种模式都会先检查 /ssr-lab 的原始 HTTP HTML,再打开浏览器验证 hydration、增强、reload 和路由往返后的稳定性。
库级 SSR 回归覆盖
仓库里还有一层直接针对渲染器的 renderToString 回归测试:
pnpm test --run test/ssr-render-to-string.test.ts test/ssr-import.test.ts这层测试显式覆盖了:
- 轻节点 SSR 组件矩阵,例如 heading、paragraph、行内格式、link、list、table、footnote、admonition、
vmr_container - 独立的
MarkdownCodeBlockNodeSSR shell - 通过
setCustomComponents做 scoped 内置覆盖 - 直接自定义 node type 的 SSR
- 通过
customHtmlTags接入的可信自定义标签 SSR