Next.js + Redoc で1秒以内でレスポンスする API 仕様書をつくった
こんにちは zane です。
Collections というオープンソースのヘッドレス CMS をつくっています。今回パブリックな API 仕様書が必要になり Next.js(Nextra) + Redoc という組み合わせを試したら、なかなか良かったので手順としてまとめてみました。
OpenAPI(Swagger)などを使った API 仕様書はだいたいどのプロジェクトでも作成しますが、それを公開するとなると、機会はあまり多くはないかもしれません。が、大きく技術トレンドが変わる分野でもないので、覚えておくといずれ役に立つかもしれません!
完成品
公開されているページはこちら
コードはすべて GitHub で公開していますので、参考にしてみてください。
Redoc とは?
OpenAPI 仕様で記述された yaml ファイルから HTML ファイルを生成し、静的なドキュメントにしてくれるツールで、オープンソースとしても公開されています。
Collections は、ドキュメント全体を Nextra (Next.jsベースの静的サイトジェネレーター) で作っていますので、これに統合してレンダリングさせています。
Nextra については、以前記事を書いていますので、参考にしてみてください。
React のコンポーネントとして Redoc をインストールする
それでは早速、公式のステップ に沿って進めていきましょう。まずは @redocly/cli
と関連する依存関係をインストールします。
npm i react react-dom mobx styled-components core-js
yaml ファイルを準備
次に、OpenAPI 仕様をもとに yaml ファイルを作成します。
Collections の API 仕様書を貼っておきますので、参考してみてください。
VSCode を使っている方は OpenAPI (Swagger) Editor
を入れておくと、文法エラーなどワーニングを出してくれるのでサクサク作業が進められます。
コンポーネントに追加する
ファイルの準備ができたらページに Redoc のコンポーネントを埋めると、自動で HTML を生成して出力してくれます!
import { RedocStandalone } from 'redoc';
<RedocStandalone specUrl="url/to/your/spec"/>
ただし specUrl
でローカルファイルを参照させることはできません。これは GitHub のイシューでもやりとりされていますが、同一オリジンポリシーとセキュリティ上の都合によるものです。
この問題の対応策として S3 などに yaml を退避させる選択肢もありますが、手間は増えるしファイルをアップロードするために CI のジョブを追加したりと、あまりやりたくはありません。。。
Next.js の API で配信し SSG 化する
そのため Next.js のAPIを使って yaml をレスポンスさせ、それを渡すことでこの問題を解決しました。
export default function handler(_req: NextApiRequest, res: NextApiResponse<ResponseData>) {
const fullPath = path.join(dataDirectory, 'api.yaml');
const fileContents = fs.readFileSync(fullPath, 'utf8');
res.status(200).json(YAML.parse(fileContents));
}
まぁ、これだけでも良かったのですが、都度リクエストが走ることでレンダリングが結構遅い。。。そのため、もう一工夫が必要です。Redoc にはspec
という URL の代わりにオブジェクトを渡すプロパティもあるので
export const getStaticProps = ({ params }) => {
return fetch(`https://collections.dev/api/openapi`)
.then((res) => res.json())
.then((repo) => ({
props: {
ssg: repo,
},
}));
};
export const Redoc = () => {
const data = useData();
return <RedocStandalone spec={data} />;
};
このように SSG で事前レンダリングしてオブジェクトを渡すことで、見事レスポンス面もクリアできました!
パフォーマンス
$ curl 'https://collections.dev/ja/reference/api/' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8,ja;q=0.6' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Connection: keep-alive' --compressed -o /dev/null -w "%{time_starttransfer}\n" -s
0.239587
0.249859
0.255718
0.249946
0.253883
と、だいたい 300ms 以内でレスポンスされます。
First Contentful Paint
も1秒くらい。これ以上改善しても SEO が求められるページでもないので、合格点を出してもいいのではないでしょうか!
最後に
ドラッグ&ドロップで WordPress を API 化するオープンソースのヘッドレス CMS 【 Collections 】をつくっています!
Markdown(with GFM) やダークモードなど、書き心地の良さも持ち味です。 Live Demo も公開していますので、ぜひ気軽に触ってみてください 🙌🙌
それでは
Discussion