サムネイル

microCMSから取得してきたデータをNext.jsを使ってRSSフィードを生成する方法

私が運営しているブログサイトにRSSフィードを実装しました。今回はその時の話をしたいと思います。

このブログサイトには、コンテンツ管理(ブログ記事)をmicroCMSで管理しているので、microCMSで管理しているブログの記事を
取得しxmlで吐いていきたいと思います。
尚、フロントエンドはNext.jsです。

ライブラリをインストール

動的にRSSフィードを実装をする上で簡単に実装できるライブラリがあるのでそれをインストールします。

$ npm install rss

また今回はtypescriptを使うので、合わせてこちらもインストールします。

$ npm install --save-dev @types/rss

getServerSidePropsで動的にRSSフィードを生成する

page/feed.tsxを作成する。

import React from "react";
import { GetServerSidePropsContext } from "next";
import generateFeed from "../functions/genalate-rss-feed";

export const getServerSideProps = async ({ res }: GetServerSidePropsContext) => {
  const xml = await generateFeed(); // フィードの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 feed = () => null;
export default feed;

getServerSidePropsを使用してRSSデータを生成し、直接レスポンスを返すことで、余計なレイアウトやメタタグなどが混入しないようにします。Pageコンポーネント内でHTMLやXMLを返しても、_app.tsx_document.tsxの中に埋め込まれるため、余計なレイアウトやメタタグなどが混じってしまう可能性があるため、直接レスポンスを返すことでそれを防ぎます。

getServerSidePropsの引数でresを受け取ることができ、HeaderにContent-TypeCache-Controlを付けた上で、res.end(RSSフィードの中身)という形でレスポンスを返します。これにより、生成されたRSSデータが正しい形式でクライアントに返されるようになります。

RSSフィードを生成する

src/functions/genalate-rss-feed.tsを作成します。ここで先ほどインストールしたrssの登場です。

import RSS from "rss";
import { createClient } from "microcms-js-sdk"; 
	
export const client = createClient({
  serviceDomain: process.env.NEXT_PUBLIC_SERVICE_DOMAIN as string, 
  apiKey: process.env.NEXT_PUBLIC_API_KEY as string,
});

const SITE_URL = "サイトのURL";

const generateFeed = async (): Promise<string> => {
  const feed = new RSS({
    title: "タイトルです",
    description: "ディスクリプションです",
    site_url: SITE_URL,
    feed_url: "/feed",
    language: "ja",
  });
  
  const data = await client.get({
    endpoint: "blog",
  	queries: {
  	  limit: 999,
  	},
  });
  data.contents.forEach((post) => {
  	feed.item({
  	  title: returnTitle(post.title),
  	  description: returnDiscription(post.body),
  	  date: new Date(post.createdAt),
  	  url: `${SITE_URL}/blog/${post.id}`,
  	});
  });
  
  // XML形式の文字列にする
  return feed.xml();
};
  
export default generateFeed;


https://zenn.dev/catnose99/articles/c7754ba6e4adac