07.VitePress配置RSS
参考:https://vitepress.vuejs.ac.cn/guide/data-loading#createcontentloader
rss这玩意我搞了整整一天,坑是真的多,我就纳闷了,这么简单而且大众的功能为毛就不出一个专门的官方教程呢,非得让用户满网瞎找, 网上大多数给的教程一点用都没有,说的驴头不照马尾,而且,写的东西真是一点让别人看的,各种提前的注意点和依赖都不说,粘上去各种报错。真实服了。
刚开始我从来没在意过rss这玩意,不就是暴漏个接口让别人可以看到你更新的文章么,也没什么大不了的,嘿,无意中发现一个网站,就是类似十年之约的 网站,想加入还必须要有这玩意,不然不给申请,那我就来了兴致,开干。骂骂咧咧的搞了一天所有的坑都走完了,总算是很完美的写出来了,对,就是 很完美的写出来了!!!
为什么说完美实现捏,因为别人教你的都是生成元数据,无一例外都需要你将你之前的文章都加上frontmatter
信息来实现对元数据的获取。比如标题,发布时间, 描述等,这工作量那是相当的大,岂不是要累死,身为一名有职业素养的程序猿,怎么可能干这些重复性的无脑操作。所以这些信息全部动态获取。只需要几秒钟即可实现RSS。
注意:但是有个bug,对于CICD全自动托管的部署
,发布时间是不准确的,因为这种压根就没有时间,发布一次就没了。无解,只能写frontmatter
, 有空再搞吧,写个脚本自动处理下。
吐槽完毕,开干。
什么是rss
就是给你的网站生成一个rss.xml文件,里面是你网站的最新的文章数据。然后暴漏出去,然后别人就可以第一时间发现你的最新的文章了。 有用么?对于大多数人没用,对于大佬来说挺有用,比如阮一峰大佬博客就支持RSS订阅。
如何实现
说白了就是写个函数,动态遍历你所有的网站文章数据,然后将数据写到rss.xml文件中。
什么时候写呢?每次发布的时候写就可以保证每次发布rss的 内容都是最新的。
xml里面都是什么数据?是一些最新文章的标题、URL、描述、等元数据信息
有插件么?vitepress没发现对应的插件,只能自己撸一个了,原理知道了,其实也很简单。
依赖
yarn add feed
RssPlugin插件
docs/.vitepress/plugins/RssPlugin.js
import path from 'node:path'
import { writeFileSync } from 'node:fs'
import fs from 'node:fs';
import { Feed } from 'feed'
import { createContentLoader } from 'vitepress'
let baseUrl = 'https://blog.share888.top'
function stripHtmlTags(html) {
return html.replace(/<[^>]*>/g, '').replace('​','').trim().substring(0, 30);
}
export async function generateRssFile(config) {
const feed = new Feed({
title: config.userConfig.title,
description:config.userConfig.description,
id: baseUrl,
link: baseUrl,
language: config.userConfig.lang,
favicon: `${baseUrl}/favicon.ico`,
copyright: `如有转载或 CV 的请标注本站原文地址. Copyright © 2022-${ new Date().getFullYear() }`,
})
let posts = await createContentLoader('**/*.md', {
excerpt: true,
render: true,
}).load()
posts = posts.filter(post => post.url.endsWith('.html'))
posts.forEach(post => {
let targetPath = config.root + post.url.replace('.html','.md')
const stats = fs.statSync(targetPath);
// 获取最后修改时间
const lastModified = stats.mtime;
// 使用 path 模块的解析功能来获取文件名
const fileNameWithExtension = path.basename(targetPath);
const fileNameObject = path.parse(fileNameWithExtension);
const fileName = fileNameObject.name;
// 在控制台输出或进行其他处理
console.log(`${fileName} last modified on ${stats.mtime.toLocaleString()}`);
post['fileName'] = fileName;
post['lastModified'] = lastModified;
post['full_url_path'] = `${baseUrl}${post.url}`;
post['description'] = stripHtmlTags(post.html);
})
posts.sort((a, b) => b['lastModified'].getTime() - a['lastModified'].getTime());
// 只保留最新的前20条
posts = posts.slice(0, Math.min(posts.length, 20));
posts.forEach(post => {
feed.addItem({
title: post.frontmatter?.title || post.fileName || '无标题',
id: `${post.full_url_path}`,
link: `${post.full_url_path}`,
guid: `${post.full_url_path}`,
description:`${post.description}`,
date: post.frontmatter?.date || post.lastModified || '无时间',
})
})
writeFileSync(path.join(config.outDir, '/rss.xml'), feed.rss2())
}
配置
docs/.vitepress/config.js
import {generateRssFile} from "./plugins/RssPlugin";
export default {
title: '卡卡罗特',
base:'/',
//en-US
lang: 'zh-CN',
// 重点配置
async buildEnd(siteConfig) {
await generateRssFile(siteConfig)
}
}
添加rss图标
//社交链接
const socialLinks= [
{
icon: {
svg: '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M3.5 3.25a.75.75 0 0 1 .75-.75C14.053 2.5 22 10.447 22 20.25a.75.75 0 0 1-1.5 0C20.5 11.275 13.225 4 4.25 4a.75.75 0 0 1-.75-.75Zm.75 6.25C10.187 9.5 15 14.313 15 20.25a.75.75 0 0 1-1.5 0A9.25 9.25 0 0 0 4.25 11a.75.75 0 0 1 0-1.5ZM3.5 19a2 2 0 1 1 3.999-.001A2 2 0 0 1 3.5 19Z"/></svg>',
},
link: '/rss.xml',
},
]
测试是否正常
执行build命令,会发现你的dist文件下出现了rss.xml文件,就说明OK了
报错
假如你启动的项目出现这个报错,vitepress使用createContentLoader时遇到["vitepress" resolved to an ESM file. ESM file cannot be loaded by
require.]
报错,需要下面解决 把 package.json中的type改为module
{
"name": "敲代码的卡卡罗特",
"version": "1.0.0",
"type": "module"
}