Feed 订阅 新
约 1461 字
概述
主题支持在构建时为站点生成 RSS 2.0、Atom 1.0 与 JSON Feed 1.1 订阅文件, 并在页面 <head> 中注入 <link rel="alternate">,让读者与自动化工具可以直接发现订阅地址。
与「一个站点一个 feed」的通用方案不同,主题的 feed 与 collections 集合模型对齐, 支持 按语言 × 集合 拆分频道:
.vuepress/dist
feed.xml
atom.xml
feed.json
blog
feed.xml
notes
feed.xml
en
feed.xml
blog
feed.xml
快速开始
配置 hostname 与 feed 即可:
import { defineUserConfig } from 'vuepress'
import { plumeTheme } from 'vuepress-theme-plume'
export default defineUserConfig({
theme: plumeTheme({
hostname: 'https://example.com',
feed: true, // 只输出 /feed.xml
}),
})必须配置 hostname
feed 中所有链接都必须是绝对地址,没有 hostname 时主题会跳过生成并输出警告。 base 也需要与站点实际部署路径一致,否则订阅地址会指向错误位置。
仅在生产构建时生效
feed 在 onGenerated 阶段生成,即只有执行 vuepress build 时才会产出文件。 开发模式(vuepress dev)下不会生成任何 feed。
多集合与多语言
集合频道
默认只输出全局频道。多集合站点可以开启 perCollection,为每个符合条件的集合输出独立频道:
export default defineUserConfig({
theme: plumeTheme({
hostname: 'https://example.com',
feed: {
perCollection: true,
formats: ['rss', 'atom', 'json'],
},
locales: {
'/': {
collections: [
{ type: 'post', dir: 'blog', title: '博客', link: '/blog/' },
{ type: 'post', dir: 'notes', title: '笔记', link: '/notes/' },
],
},
},
}),
})产物:
| 频道 | 输出文件 | 公开地址 |
|---|---|---|
| 全局频道 | dist/feed.xml | https://example.com/feed.xml |
| 博客频道 | dist/blog/feed.xml | https://example.com/blog/feed.xml |
| 笔记频道 | dist/notes/feed.xml | https://example.com/notes/feed.xml |
同一篇文章可能同时出现在全局频道与集合频道中,这是预期行为。
集合级开关
集合上的 feed 决定该集合是否纳入订阅、是否生成独立频道:
// doc 集合默认不纳入 feed,`feed: true` 即为显式开启
const doc = { type: 'doc', dir: 'guide', title: '指南', sidebar: 'auto', feed: true }// 关闭某个集合的订阅
const post = { type: 'post', dir: 'notes', title: '笔记', feed: false }feed: true 等价于 feed: {},都会让该集合纳入 feed 并生成独立频道, 且不再受主题级 perCollection / includeDocCollections 限制。
具体字段请参考 集合配置。
多语言
每个语言环境至少输出一个全局频道,输出路径与 locale 前缀对齐:
dist/feed.xml → https://example.com/feed.xml
dist/en/feed.xml → https://example.com/en/feed.xmlchannel.link 与集合的 feed.link 都是 locale 相对路径(例如 /blog/), 主题会自动补上当前语言前缀,不要在配置中重复写 /en/。
自定义文件名与目录
export default defineUserConfig({
theme: plumeTheme({
feed: {
filename: {
rss: 'rss.xml',
atom: 'atom.xml',
json: 'feed.json',
},
channel: {
link: '/subscribe/', // 全局频道输出到 dist/subscribe/
title: '订阅',
author: { name: 'pengzhanbo', email: 'i@example.com' },
ttl: 60,
},
}
})
})全文模式与体积权衡
content 默认为 'excerpt',只输出摘要;设置为 'full' 时会输出正文 HTML。
全文模式不渲染 Vue 组件
feed 的正文来自构建期的 page.contentRendered,其中主题与 vuepress-plugin-md-power 提供的 Vue 组件(<VPBadge>、<VPCard>、REPL、图表等)尚未被浏览器解析。 生成时这些组件标签会被剥离,仅保留内部文本,读者需要回到原页面查看交互内容。
全文模式会显著增大文件体积。单个频道超过 10 MB 时,构建日志会给出警告,建议改用 content: 'excerpt' 或调小 limit。
安全与隐私
以下页面/内容 不会 进入任何 feed:
| 场景 | 处理 |
|---|---|
页面设置了 password | 排除 |
命中 encrypt.rules | 排除 |
encrypt.global 全站加密 | 整个 feed 功能禁用并警告 |
frontmatter.draft: true | 排除 |
frontmatter.article: false | 排除 |
frontmatter.feed: false | 排除(优先级最高) |
| 首页 / 文章列表 / 标签页等非内容页 | 排除 |
::: encrypt 加密片段 | 正文中的对应标签被移除 |
单页排除:
---
title: 内部草稿思路
feed: false
---也可以覆盖单个条目的元信息:
---
title: 文章标题
feed:
title: 订阅器中显示的标题
summary: 自定义摘要
guid: /custom-id/
---自动发现
构建时,属于某个已生成频道的页面会在 <head> 中注入对应的链接:
<link rel="alternate" type="application/rss+xml" title="博客" href="https://example.com/blog/feed.xml">- 每种启用的格式注入一条;
- 页面已声明同类型的
alternate链接时不会重复注入; linkTag: false可关闭此行为。
读者只需在 Feedly / Inoreader / NetNewsWire 等阅读器中粘贴站点域名,即可自动发现订阅地址。
校验
- RSS / Atom:https://validator.w3.org/feed/
- JSON Feed:https://validator.jsonfeed.org/
本地验证确定性:
pnpm docs:build
shasum dist/feed.xml dist/atom.xml dist/feed.json
# 再次构建后比较,结果应当一致常见问题
请检查站点配置中的 hostname 是否为合法的站点源(origin,例如 https://example.com)。 若站点部署在子路径,请使用 base(例如 /docs/)而不是把路径写进 hostname。
频道输出路径 = 频道主页路由 + 文件名。两个集合使用同一个 link 时会产生冲突, 主题会保留先出现的频道并输出警告。请通过 collections[].feed.link 指定不同的频道链接。
feed 使用「本地时间 + 时区偏移」输出,例如 2025-06-10T08:00:00+08:00。 若构建机器的时区与作者所在时区不同,字符串会不同,但表示的是同一时刻。 CI 环境固定 TZ=Etc/UTC 时产物可复现。
feed 需要发布时间:frontmatter.createTime → frontmatter.date → git.createdTime → git.updatedTime,全部缺失的页面会被跳过,构建日志中会统计跳过数量。 另外请检查页面是否被加密、标记为草稿,或设置了 article: false / feed: false。
onGenerated 只在生产构建时触发。请执行 vuepress build 后使用静态服务器预览产物。
