Next.jsで作ってるブログでRSSフィードを出力する

Next.jsで作ってるブログでRSSフィードを出力する
Photo by Andrew Neel / Unsplash

このブログのRSSを出力したい機運が高まってきたので、Next.jsでのRSSフィードの出力方法を解説します。

他に良い方法があるかもしれないです。よければ教えてください!

RSSフィードを出力するのに使えそうなnpmが2つあります。
rssfeedですが、今回はfeedを使います。

参考にしたcatnoseさんはrssの方を使ってました。どちらでもやりたいことはできるのでどちら使っても良いと思います。

feedにした理由は

  1. rssの方が最終リリースが5年前と古い
  2. rssの方が依存が多い

    mime-typesxmlの2つ。xmlの方は最終更新日が6年前である。
  3. feedは依存しているのがxml-jsだけ

依存は少ないほうがやっぱり良いですよね。

ってことでやっていきます。

手順

①feedを追加する

$ yarn add feed

②RSSフィードを出力するページを作る

ほぼ、参考にしたcatnoseさんの記事と同じです。

import { GetServerSidePropsContext } from 'next'
import { generateFeed } from '@/libs/api/feed'

export const getServerSideProps = async ({
  res,
}: GetServerSidePropsContext) => {
  const xml = await generateFeed() // 実際にRSSフィードを生成する処理(後述)

  res.statusCode = 200
  res.setHeader('Cache-Control', 's-maxage=86400, stale-while-revalidate') // 24時間キャッシュする
  res.setHeader('Content-Type', 'text/xml')
  res.end(xml)

  return {
    props: {},
  }
}

const Page = () => null
export default Page

③RSSフィードを生成する処理を作る

import { Feed } from 'feed'
import dayjs from 'dayjs'

export const generateFeed = async () => {
  const baseUrl = 'https://www.deg84.com'

  const feed = new Feed({
    title: "deg84's blog",
    description: '',
    id: baseUrl,
    link: baseUrl,
    language: 'ja',
    copyright: `© 2020 deg84`,
    updated: dayjs().toDate(), // 日付系はdayjsを使うことにしているので。new Date()でも良い。
    author: {
      name: 'deg84',
    },
    feed: `${baseUrl}/feed`,
  })

  const posts = await getPosts() // 何らかの方法で記事一覧を取得する

  posts.forEach(post => {
    const url = `${baseUrl}/${post.slug}`
    feed.addItem({
      title: post.title,
      description: post.description,
      content: post.content,
      id: url,
      link: url,
      date: dayjs(post.publishedAt).toDate(),
    })
  })

  return feed.rss2() // Atom形式でデータが欲しい場合は`feed.atom`を使う。
}

以上で出力できるようになってるはずです。

結果

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>deg84's blog</title>
        <link>https://www.deg84.com</link>
        <description></description>
        <lastBuildDate>Wed, 18 May 2022 09:05:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>ja</language>
        <copyright>© 2020 deg84</copyright>
        <atom:link href="https://www.deg84.com/feed/" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[ Next.jsで作ってるブログでRSSフィードを出力する ]]></title>
            <link>https://www.deg84.com/create-rss-feed-with-nextjs</link>
            <guid>https://www.deg84.com/create-rss-feed-with-nextjs</guid>
            <pubDate>Wed, 18 May 2022 09:30:00 GMT</pubDate>
            <description><![CDATA[ descriptionが入ります ]]></description>
            <content:encoded><![CDATA[ contentが入ります ]]></content:encoded>
        </item>
        <!-- 以下同じような感じで一覧が並ぶ -->
    </channel>
</rss>

出力されているXMLはW3C Feed Validation Service, for Atom and RSS等でチェックしておきます。

さいごに

昔はHTMLのheadにlinkでRSSフィードのURLを張ってた気がするんだけど最近それはやらない系なんだろうか?

<link rel="alternate" type="application/rss+xml" title="deg84's blog feed" href="https://www.deg84.com/feed/" />

こんなやつ

参考

Next.jsで動的にRSSフィードを生成する