📰

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

2021/01/31に公開
3

先日Next.jsでXML Sitemapを生成する方法を書きました。同じ要領でRSSフィードの実装もできるので記事にしておきます。

Next.jsのgetServerSidePropsで動的にRSSフィードを生成

Next.js(TypeScript)のPageコンポーネントの中で実装を行います。例として/feedにアクセスしたときにRSSフィードが表示されるように/pages/feed.tsxというファイルを作成します。

getServerSidePropsを使う理由

このサンプルでは、RSSデータの生成からレスポンスの返却までgetServerSidePropsの中で行います。getServerSidePropsは本来はPageコンポーネント内で使うpropsを取得するためのものですが、ここではpageコンポーネントを介さずに直接レスポンスを返却してしまいます。

というのもPageコンポーネント内でHTMLやXMLを返しても、_app.tsx_document.tsxの中に埋め込まれることになるため、レイアウトやメタタグなど余計なものが混じってしまうためです。

サンプルコード

pages/feed.tsx
import { GetServerSidePropsContext } from 'next';

export const getServerSideProps = async ({ res }: GetServerSidePropsContext) => {
  const xml = await generateFeedXml(); // フィードのXMLを生成する(後述)

  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;

getServerSidePropsの引数でresを受け取ることができるので、HeaderにContent-TypeCache-Controlをつけたうえでres.end(RSSフィードの中身)という形でレスポンスを返します。

RSSフィードの生成

あとはRSSフィード自体の生成ですが、ここではrssというnpmライブラリを使うことにします.

$ npm install rss
$ npm install --save-dev @types/rss
import RSS from 'rss';

async function generateFeedXml() {
  const feed = new RSS({
    title: "タイトル",
    description: "説明",
    site_url: "サイトのURL",
    feed_url: "フィードページのURL",
    language: 'ja',
  });

  // 例としてpostsを含めるイメージ
  // このあたりの書き方はライブラリのドキュメントを参考にしてください
  const { posts } = await getPosts();
  posts?.forEach((post) => {
    feed.item({
      title: post.title,
      description: post.description,
      date: new Date(post.createdAt),
      url: `${サイトのURL}/${post.path}`,
    });
  })
  
  // XML形式の文字列にする
  return feed.xml();
}

これをさきほどのgetServerSidePropsの中から呼べば完了です。生成したRSSが正しい形式になっているかどうかはW3CのFeed Validation Service等でチェックする良いでしょう。

Discussion

わたるわたる

とても参考になる記事有難うございます!

本当に些細な箇所ですが、一連の流れ的に

feed.xml();

return feed.xml();になりそうです。

catnosecatnose

あっ…、ありがとうございます!修正しました。