nuxt-content 不直接渲染 HTML 文件,因其仅原生支持 .md 文件解析,对 .html 文件不注册解析器、不纳入内容管道,导致 queryContent 查不到且无法生成 body/toc 等字段。
为什么 nuxt-content 不直接渲染 HTML 文件中的标签
因为 nuxt-content 默认只处理 .md(markdown)文件,它用的是 @nuxtjs/mdc(旧版是 @nuxtjs/content 的 markdown 解析器),对纯 .html 文件不注册解析器、不走内容管道,直接 404 或返回原始字符串。
- 你放一个
content/articles/test.html,queryContent('articles').find()根本查不到它 - 即使手动读取
fs.readFileSync,也绕不过nuxt-content的响应式数据层和内置转换逻辑 -
.html不是 Content 模块的“一等公民”,没有body、toc、excerpt等字段注入
怎么让 nuxt-content “认出”并解析 HTML 内容
核心思路:不硬塞 .html 文件进 content/ 目录走原生流程,而是把它当普通静态资源加载,再用 nuxt-content 的 <nuxt-content></nuxt-content> 组件手动喂给它——靠 document 对象模拟内容结构。
- 把 HTML 文件放在
static/下(如static/docs/api.html),避免被 Content 模块扫描干扰 - 在页面中用
useFetch或$fetch加载它,注意加headers: { 'Accept': 'text/html' }防止被 JSON 化 - 把响应文本包装成符合
nuxt-content输入格式的对象:{ body: { type: 'root', children: [...] }, ... }——但更简单的是用remark-html+rehype-stringify预转,或直接用v-html - 真正推荐的做法:别强求
nuxt-content解析 HTML,改用<div v-html="rawHtml"></div>渲染,再手动补 toc(如果需要)
<nuxt-content></nuxt-content> 能不能直接显示 HTML 字符串
不能。它只接受由 Content 模块解析后的 AST 对象(如 body 是 remark tree),传入字符串会静默失败或报 Cannot read property 'type' of undefined。
- 错误写法:
<nuxt-content :document="{ body: '<p>hello</p>' }" />→ 渲染空白 - 正确过渡方案:
<div v-html="fetchedHtml"></div>,配合DOMPurify.sanitize()做基础 XSS 防御 - 若必须用
<nuxt-content></nuxt-content>,得先把 HTML 字符串用retext+remark-rehype+rehype-stringify转成 AST,成本远超收益 - 注意:Nuxt 3 中
@nuxtjs/mdc支持<script setup lang="ts">和内联组件,但依然不支持直接导入 .html
替代路径:用 defineContentEventHandler 手动接管 HTML 内容
这是 Nuxt 3.7+ 提供的底层能力,可以绕过默认文件扩展名限制,把任意后缀(包括 .html)当作内容源处理。
- 在
server/content/[...slug].ts中写自定义 handler,读取event.context.params.slug对应的static/下 HTML 文件 - 用
readFileSync读取,再用remark+rehype转成兼容的 content AST(需手动构造body字段) - 返回对象必须含
_id、body(AST)、title等字段,否则queryContent查不到 - 性能隐患:每次请求都 fs 读取 + AST 转换,没缓存的话比直接
v-html慢得多
实际项目里,90% 的 HTML 内容展示需求,用 v-html + useAsyncData 加载静态文件,比折腾 Content 模块解析 HTML 更稳、更快、更可控。
立即学习“前端免费学习笔记(深入)”;











