Nuxt `content/` 目录实战:使用 @nuxt/content 模块构建基于文件的 CMS
本文以 Nuxt 仓库中 content/ 目录文档 为核心,讲解如何在 Nuxt 项目中启用 @nuxt/content 官方模块、组织 content/ 目录下的内容文件,并通过 catch-all 路由与 <ContentRenderer> 组件完成内容页面的渲染。读完后,你可以独立完成"安装模块 → 编写 Markdown/YAML/CSV/JSON 内容 → 按 URL 查询并渲染"这一完整链路,并在 Nuxt 中搭建出无需数据库的轻量级 CMS。
content/ 目录是什么
Nuxt Content 模块会读取项目根目录下的 content/ 目录,解析其中的 .md、.yml、.csv 和 .json 文件,从而为你的应用创建一个基于文件的 CMS(File-based CMS)。它提供的核心能力包括:
- 使用内置组件渲染内容;
- 使用类 MongoDB 的查询 API 查询内容;
- 在 Markdown 文件中通过 MDC(Markdown Data Components)语法直接使用 Vue 组件;
- 自动生成导航(navigation)。
content/ 是项目顶层目录,与 app/、public/、server/ 等目录并列。该模块属于 @nuxt/ scope 的官方模块,由 Nuxt 团队维护(可参考 生态模块说明)。模块启用后,Nuxt 会在其配置项下挂出模块配置,配置键名为 content,这一点在 Layers 文档 中给出的常见模块配置键示例(image、pinia、content)里可以得到印证。
第一步:启用 Nuxt Content
只需一条命令即可同时完成"安装 @nuxt/content 依赖"与"把它写入 nuxt.config.ts 的 modules"两件事:
npx nuxt module add content
执行后,nuxt.config.ts 中会多出 modules: ['@nuxt/content'](或 content)这一配置。关于模块的加载时机,从 modules/ 目录文档 可以确认执行顺序为:
- 先加载
nuxt.config.ts中声明的模块(@nuxt/content会走这里); - 再按字母序执行
modules/目录下的本地模块。
也就是说,content 模块在应用启动早期就已就绪,其后声明的本地模块可以在 build 阶段直接引用内容目录约定。
第二步:创建内容文件
把 Markdown 文件放入 content/ 目录即可,例如:
<!-- content/index.md -->
# Hello Content
模块会自动发现并解析这些文件,无需任何额外配置。除 .md 外,.yml(结构化数据)、.csv(表格数据)、.json(通用结构化数据)同样会被解析并纳入内容集合,供后续查询使用。
第三步:渲染内容页面(catch-all 路由)
要让每个内容文档都对应一个可访问的 URL,需要添加一个 catch-all 路由配合 <ContentRenderer> 组件。
在 Nuxt 中,catch-all 路由通过命名为 [...slug].vue 的页面文件创建,它会匹配该路径下的所有路由;从 pages 目录文档的 Catch-all Route 一节 可知,访问 /hello/world 时 $route.params.slug 的值为 ["hello", "world"]。仓库内的测试 fixture 中也存在一个真实的多段 catch-all 用法,可参考 catch-all fixture。
完整渲染示例如下(继承自原文档,可直接复制使用):
<!-- app/pages/[...slug].vue -->
<script lang="ts" setup>
const route = useRoute()
const { data: page } = await useAsyncData(route.path, () => {
return queryCollection('content').path(route.path).first()
})
</script>
<template>
<div>
<header><!-- ... --></header>
<ContentRenderer
v-if="page"
:value="page"
/>
<footer><!-- ... --></footer>
</div>
</template>
这段代码里有几个值得注意的技术细节:
useAsyncData以route.path作为缓存键:切换 URL 时 key 变化,Nuxt 会重新执行查询,从而按路径拉取对应的内容文档,实现"路由驱动的内容加载";queryCollection('content').path(route.path).first():这是 Nuxt Content 提供的类 MongoDB 查询 API,在content集合中按path字段匹配当前路由并取第一条记录,命中即返回该文档的完整数据;<ContentRenderer v-if="page" :value="page" />:内置渲染组件负责把查询结果(含 Markdown 解析树)转换为 Vue 组件树;v-if保证查询无结果时跳过正文渲染,页面框架(header/footer)仍然保留,可作为未命中内容时的兜底结构;- 页面整体保持单一根元素(
<div>包裹),这是 Nuxt 页面参与路由过渡的前提,见 pages 文档的说明。
查询 API 与 MDC 语法
原文档将深入内容留给了 Nuxt Content 官方文档,这里概括其两大进阶方向,供你按需深入:
- 类 MongoDB 查询 API:
queryCollection支持按字段条件、排序、分页等方式对内容集合进行检索,上面的path(...).first()只是最基础的路径匹配用法,复杂场景可组合更多查询操作符; - MDC(Markdown Data Components)语法:允许在
.md文件中直接编写 Vue 组件及其属性、事件,从而把交互组件嵌入内容文档,无需为每篇文档单独建页。
这两项能力均由 @nuxt/content 模块自身实现,Nuxt 仓库提供的是 content/ 目录约定与页面侧的渲染接入点。
小结与延伸阅读
按本文链路操作后,你的项目结构大致为:
-| content/
---| index.md # 内容文件,自动解析
---| guide/
-----| getting-started.md
-| app/
---| pages/
-----| [...slug].vue # catch-all 路由 + <ContentRenderer>
结合仓库中的相关文档可继续深入:
- content/ 目录文档(原文档):模块定位、安装命令与渲染示例;
- pages/ 目录文档:动态路由与 catch-all 路由的完整规则;
- modules/ 目录文档 与 模块开发指南:理解
@nuxt/content作为外部模块的加载与配置机制; - 目录结构总览:
content/在整个 Nuxt 项目约定中的位置。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00