私が運営しているブログサイトにRSSフィードを実装しました。今回はその時の話をしたいと思います。
このブログサイトには、コンテンツ管理(ブログ記事)をmicroCMSで管理しているので、microCMSで管理しているブログの記事を
取得しxmlで吐いていきたいと思います。
尚、フロントエンドはNext.jsです。
動的にRSSフィードを実装をする上で簡単に実装できるライブラリがあるのでそれをインストールします。
$ npm install rss
また今回はtypescriptを使うので、合わせてこちらもインストールします。
$ npm install --save-dev @types/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-Type
やCache-Control
を付けた上で、res.end(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;