Skip to content
鼓励作者:欢迎打赏犒劳

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没发现对应的插件,只能自己撸一个了,原理知道了,其实也很简单。

依赖

shell
yarn add feed

RssPlugin插件

docs/.vitepress/plugins/RssPlugin.js

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('&ZeroWidthSpace;','').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

js
import {generateRssFile} from "./plugins/RssPlugin";

export default {
    title: '卡卡罗特',
    base:'/',
    //en-US
    lang: 'zh-CN',
    
    // 重点配置
    async buildEnd(siteConfig) {
        await generateRssFile(siteConfig)
    }
}

添加rss图标

js
//社交链接
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

json
{
    "name": "敲代码的卡卡罗特",
    "version": "1.0.0",
    "type": "module"
}

如有转载或 CV 的请标注本站原文地址