RSSフィードを生成するようにした

https://tech.mkr-note.net/rss.xmlでRSSフィードを作成するようにした。未だ?にRSSフィードを愛用している自分用となっている。読みたいWebサイトの巡回とか皆どうしているのだろうか。今の時代だと「話題はSNSでキャッチアップ!」でどうたら…という話題になりそうな気もするけど、全てがSNSで完結するわけでもないと思うので、単純な疑問として存在している。そもそももう PC でWebサイトを巡回するしぐさがおじさん的な行為なのだろうか。

Astro の RSSフィード生成は @astrojs/rss パッケージを使用して実装することができる。ドキュメントも用意されているので、基本的にはこちらに準じた。記事エントリの名前(title)やエントリURL(link)を詰める itemsリストは基本的にファイル生成時に自動的に保管してもらうことを目指すことになる。ドキュメント内では glob を使用するパターンと、コンテンツコレクションを使用するパターンが紹介されていた。

glob を使用するパターン

pagesGlobToRssItems()を利用して、ディレクトリに存在する md or mdx拡張子のファイルから Frontmatter の情報を収集し、そのまま RSS の itemsとして当てはめている動作だった。

最初はこれで実装しようかなと思っていたが、そのまま Frontmatter を引っ張ってくるため、Frontmatter の要素と RSS を構成する上で必須となる items 要素 が一致しなくてはいけない。ここで必須となる要素のうちの一つ、pubDate が記事ファイルの Frontmatter に含まれていなかったため、単純に書くだけではダメそうだった。

コンテンツコレクションを使用するパターン

コンテンツコレクションsrc/content 配下にフォルダを作成して、そのフォルダ配下の md or mdx ファイルに対してデータコレクションを作成し、そのコレクションから情報を引っ張り出して、他のものに使用していこうという機能らしい。以前ドキュメントを見たときに使ってみたいな、と思っていたことおあったのでこちらも試してみることにした。

コンテンツコレクションの作成

コンテンツコレクションは、src/content/config.ts より作成する。コレクションとして作成したい情報をこちらに記載することになる。

import { z, defineCollection } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    date: z.date(),
  }),
})

export const collections = {
  'blog': blogCollection,
};

公式ドキュメントに記載されているものをほぼそのまま使用させてもらっている。JS/TSが全くわからないため import の書き方に対して全くしっくり来ていない…。それは置いておいて、内容からなんとなくやりたいことはわかったのでよしとする。zは TS のスキーマを検証するライブラリ colinhacks/zod のようで、astro が内部的に使用しているものとのこと。

コンテンツコレクションのためのディレクトリ

src/content に直接md or mdxファイルを置くのではなく、コレクション毎にディレクトリを作成するよう記載があるのでそのようにする。上記のコードで blog を指定しているので、src/content/blog/ ディレクトリを新しく切り、その中にmd or mdxファイルを配置している。

RSSの生成

次に RSS を生成する。RSS は上述の @astrojs/rss を使用して生成するために、src/pages/rss.xml.js を作成する。

import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';

export async function GET(context) {
        const blog = await getCollection('blog');
        return rss({
                title: 'まっくらのーと',
                description: 'ここは説明です。',
                site: context.site,
                items: blog.map((post) => ({
                        title: post.data.title,
                        pubDate: post.data.date,
                        link: `${post.slug}/`,
                })),
                customData: '<language>ja-JP</language>',
        });
}

こちらも公式ドキュメントほぼそのまま。itemsの要素を少しいじったくらい。何も分からない状態ではあるけど、getCollection()で生成したコレクションを持ってきて、itemsに要素を詰め込んでいることぐらいはわかるのでこちらもよしとする。

link で使用しているslugは、こちらに説明がある。ファイル名からページURLにも使用される文字列を生成していてslugに格納される。上記ではそれを直接 link に指定している。

RSSフィードのリンクの修正

astro.config.mjssite を本ブログのURLに修正する。ここが <channel>><link>の要素になる。

おわりに

自分用メモとして RSS 生成するためにやったことを整理した。いくつかのコードを記載する必要はあったがドキュメントに記載されていたおかげで、まあまあ楽に実装できたのでよかったよかった。

© てっくらのーと/mkr-note 2024