RSS 订阅源
为你的站点生成 RSS 订阅源,让用户可以订阅更新。
使用 vitepress-plugin-rss
安装
bash
npm install vitepress-plugin-rss -D配置
ts
// .vitepress/config.mts
import { rssPlugin } from 'vitepress-plugin-rss'
export default defineConfig({
vite: {
plugins: [
rssPlugin({
title: 'VitePress 学习指南',
description: 'VitePress 官方中文教程',
baseUrl: 'https://your-domain.com',
copyright: 'Copyright 2026',
output: {
rss: true, // 输出 rss.xml
atom: true, // 输出 atom.xml
json: true // 输出 feed.json
}
})
]
}
})手动生成 RSS
安装依赖
bash
npm install feed gray-matter -D创建生成脚本
ts
// scripts/generate-rss.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { Feed } from 'feed'
const SITE_URL = 'https://your-domain.com'
const SITE_TITLE = 'VitePress 学习指南'
const SITE_DESC = '从零开始学习 VitePress'
const feed = new Feed({
title: SITE_TITLE,
description: SITE_DESC,
id: SITE_URL,
link: SITE_URL,
language: 'zh-CN',
image: `${SITE_URL}/logo.png`,
favicon: `${SITE_URL}/favicon.ico`,
copyright: `Copyright © ${new Date().getFullYear()}`,
updated: new Date(),
feedLinks: {
rss: `${SITE_URL}/rss.xml`,
atom: `${SITE_URL}/atom.xml`,
json: `${SITE_URL}/feed.json`
},
author: {
name: 'VitePress 学习指南',
link: SITE_URL
}
})
interface Article {
title: string
path: string
date: Date
excerpt: string
content: string
tags: string[]
}
const articles: Article[] = []
function walk(dir: string) {
const entries = fs.readdirSync(dir, { withFileTypes: true })
for (const entry of entries) {
const fullPath = path.join(dir, entry.name)
if (entry.isDirectory() && !entry.name.startsWith('.')) {
walk(fullPath)
} else if (entry.name.endsWith('.md')) {
const content = fs.readFileSync(fullPath, 'utf-8')
const { data, content: body } = matter(content)
if (!data.date) continue
articles.push({
title: data.title || entry.name,
path: fullPath.replace('docs/', '').replace('.md', ''),
date: new Date(data.date),
excerpt: body.slice(0, 200).replace(/[#*`\[\]]/g, ''),
content: body,
tags: data.tags || []
})
}
}
}
walk('docs')
// 按日期排序,取最近 20 篇
articles
.sort((a, b) => b.date.getTime() - a.date.getTime())
.slice(0, 20)
.forEach(article => {
const url = `${SITE_URL}/${article.path}`
feed.addItem({
title: article.title,
id: url,
link: url,
description: article.excerpt,
content: article.content.slice(0, 1000),
author: [{ name: 'VitePress 学习指南' }],
date: article.date,
category: article.tags.map(tag => ({ name: tag }))
})
})
// 输出文件
fs.writeFileSync('docs/public/rss.xml', feed.rss2())
fs.writeFileSync('docs/public/atom.xml', feed.atom1())
fs.writeFileSync('docs/public/feed.json', feed.json1())
console.log('✅ RSS 订阅源已生成')构建时运行
json
// package.json
{
"scripts": {
"prebuild": "tsx scripts/generate-rss.ts"
}
}添加订阅链接
在 head 中添加
ts
// .vitepress/config.mts
export default defineConfig({
head: [
['link', { rel: 'alternate', type: 'application/rss+xml', title: 'RSS', href: '/rss.xml' }],
['link', { rel: 'alternate', type: 'application/atom+xml', title: 'Atom', href: '/atom.xml' }],
['link', { rel: 'alternate', type: 'application/json', title: 'JSON Feed', href: '/feed.json' }]
]
})订阅按钮组件
vue
<!-- .vitepress/theme/components/RssButton.vue -->
<script setup lang="ts">
const feeds = [
{ name: 'RSS', url: '/rss.xml', icon: 'rss' },
{ name: 'Atom', url: '/atom.xml', icon: 'atom' },
{ name: 'JSON', url: '/feed.json', icon: 'json' }
]
</script>
<template>
<div class="rss-links">
<a
v-for="feed in feeds"
:key="feed.name"
:href="feed.url"
class="rss-link"
target="_blank"
>
<svg class="icon" viewBox="0 0 24 24" width="16" height="16">
<path
fill="currentColor"
d="M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20C5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27V4.44m0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93V10.1Z"
/>
</svg>
{{ feed.name }}
</a>
</div>
</template>
<style scoped>
.rss-links {
display: flex;
gap: 0.75rem;
}
.rss-link {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.5rem 1rem;
background: var(--vp-c-bg-alt);
border-radius: 8px;
color: var(--vp-c-text-1);
text-decoration: none;
font-size: 0.875rem;
transition: all 0.2s;
}
.rss-link:hover {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand-1);
}
</style>完整文章内容
如果需要输出完整文章内容:
ts
import MarkdownIt from 'markdown-it'
const md = new MarkdownIt({
html: true,
linkify: true
})
// 在添加文章时
feed.addItem({
// ...
content: md.render(article.content),
// 或者只输出纯文本
// content: md.render(article.content).replace(/<[^>]*>/g, '')
})