Skip to content

VitePress站点生成RSS并自动部署刷新阿里云CDN

简述

利用buildEnd构建钩子在站点构建完成后自动上传部署,并刷新静态页面CDN缓存。

在构建钩子中生成RSS并部署

在docs.vitepress\config.mts文件中添加如下设置:

ts
import { defineConfig } from 'vitepress'
import createRssFile from './theme/rss'
import ssh from './theme/ssh'

export default defineConfig({
  sitemap: {
    hostname: '****'
  },
  buildEnd(siteConfig) {
    //生成rss后ssh上传
    createRssFile(siteConfig).then(() => ssh(siteConfig))
  },
})

RSS生成脚本

新建ts文件(如docs.vitepress\theme\rss.ts)

ts
import path from "path";
import { writeFileSync } from "fs";
import { Feed } from "feed";
import { createContentLoader, type SiteConfig } from "vitepress";


export default async function createRssFile(config: SiteConfig): Promise<void> {
    const hostname = config.sitemap?.hostname || 'https://fuxes.cn'

    const feed = new Feed({
        title: "****",
        description: "****",
        id: hostname,
        link: hostname,
        language: "zh-CH",
        image: hostname + "/favicon.ico",
        favicon: hostname + "/favicon.ico",
        copyright: "****",
    });

    const posts = await createContentLoader(['**/*.md'], {
        includeSrc: true,
        excerpt: true,
        render: true,
        transform(rawData) {
            return rawData
                .map(e => {
                    return {
                        url: e.url,
                        html: e.html,
                        excerpt: e.excerpt,
                        //我的md博文最后都有成文时间,也可用fs.statSync读取文件mtime;
                        date: new Date(e.src!.slice(-10))
                    }
                })
                //检查日期是否有效
                .filter(e => !Number.isNaN(e.date.getTime()))
                .sort((a, b) => b.date.getTime() - a.date.getTime())
                .slice(0, 3)
        },
    }).load();

    for (const { url, excerpt, html, date } of posts) {
        const title = url.slice(url.lastIndexOf('/') + 1)
        feed.addItem({
            title,
            id: `${hostname}${url}`,
            link: `${hostname}${url}`,
            content: html,
            author: [
                {
                    name: "****",
                    email: "****",
                    link: hostname,
                },
            ],
            date: date,
        });
    }

    writeFileSync(path.join(config.outDir, "feed.xml"), feed.rss2(), "utf-8")
    console.log('rss build complete')
}

部署后自动刷新CDN

部署脚本具体见Node SSH,在上传文件的回调函数中调用CDN刷新脚本

js
import Cdn from './cdn'

ssh.connect({
  //...
}).then(function () {
    //...
    ssh.putDirectory('D:\\****\\docs\\.vitepress\\dist', '/usr/local/nginx/html', {
      //...
    }).then(function (status) {
      console.log(`deploy ${status ? 'successful' : 'unsuccessful'}:${successful.length},fail:${failed.join(',')}`)
        //只需刷新静态网页即可,url列表从构建钩子参数siteConfig的page中获取,也可以用fs递归读取docs文件夹的md文件
        let htmls = config.pages.map(e => e.replace(/index\.md$/, '').replace(/\.md$/, ''))
        htmls.push('feed.xml')
        htmls.push('hashmap.json')
        htmls.push('sitemap.xml')
        Cdn.refresh(htmls.map(e => config.sitemap?.hostname + '/' + e))
            .finally(() => process.exit(1))
    })
})

CDN刷新脚本

sh
$ npm install --save @alicloud/cdn20180510@5.0.0
$ npm install @alicloud/credentials  
$ npm install @alicloud/openapi-client
  • 新建js文件(如docs.vitepress\theme\cdn.js)
js
// This file is auto-generated, don't edit it
// 依赖的模块可通过下载工程中的模块依赖文件或右上角的获取 SDK 依赖信息查看
import Cdn20180510 from '@alicloud/cdn20180510'
import OpenApi from '@alicloud/openapi-client'
import Util from '@alicloud/tea-util'
import Credential from '@alicloud/credentials'

class Cdn {

  /**
   * 使用凭据初始化账号Client
   * @return Client
   * @throws Exception
   */
  //该方法会默认优先读取系统环境变量中的key和secret(设置完环境变量后需重启终端/编辑器刷新)
  static createClient() {
    let credential = new Credential.default();
    let config = new OpenApi.Config({
      credential: credential,
    });
    config.endpoint = `cdn.aliyuncs.com`;
    return new Cdn20180510.default(config);
  }

  static async refresh(urls) {
    let client = Cdn.createClient();
    let refreshObjectCachesRequest = new Cdn20180510.RefreshObjectCachesRequest({
      objectPath: urls.map(e => encodeURI(e)).join('\n'),
      objectType: "File",
    });
    let runtime = new Util.RuntimeOptions({});
    try {
      // 复制代码运行请自行打印 API 的返回值
      await client.refreshObjectCachesWithOptions(refreshObjectCachesRequest, runtime);
      console.log(`refresh successful ${urls.length}`)
    } catch (error) {
      // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
      // 错误 message
      console.log(error.message);
      // 诊断地址
      console.log(error.data["Recommend"]);
      Util.default.assertAsString(error.message);
    }
  }

}

export default Cdn

结语

设置完成,运行命令即可一键生成rss并自动部署刷新。

sh
$ npm run docs:build

正常运行显示如下:

sh
> docs:build
> vitepress build docs


  vitepress v1.5.0

 building client + server bundles...
 rendering pages...
 generating sitemap...
build complete in 5.06s.
rss build complete
deploy successful:**,fail:
refresh successful **

2025-04-25