amp-listを使ってNext.jsの静的サイトに他のブログ記事への誘導をランダムでつける
TL;DR
ブログでよくある、関係のある記事をランダムで記事の一番下につけたかったのですが、静的サイトだとどうすればいいのかよくわかりませんでした。一つは毎回ServersideProps
呼ぶ、ということだと思うんですが、それとgetStaticsProps
の併用、どうやるんだ?ってところでよくわからなくなりました。毎回サーバーサイドレンダリングしてると、遅くなりそうで嫌なので...
そこで、今回とったアプローチは、Next.jsでAPIをまず実装し、それをamp-list
を使ってfetchしてその結果をレンダリングするというアプローチを取りました。
amp-listとamp-mustache
amp-list
は、AMPの拡張コンポーネントでJSONエンドポイントから動的にデータを取得し、amp-mustache
のtemplateを使用してレンダリングを行うことができます。
公式ドキュメント(amp-list, amp-mustache)の例は以下の感じです。
<amp-list width="auto"
height="100"
layout="fixed-height"
src="/static/inline-examples/data/amp-list-urls.json">
<template type="amp-mustache">
<div class="url-entry">
<a href="{{url}}">{{title}}</a>
</div>
</template>
</amp-list>
使用しているJSONは以下
{
"items": [
{
"title": "AMP YouTube Channel",
"url": "https://www.youtube.com/channel/UCXPBsjgKKG2HqsKBhWA4uQw"
},
{
"title": "AMP.dev",
"url": "https://amp.dev/"
},
{
"title": "AMP Validator",
"url": "https://validator.amp.dev/"
},
{
"title": "AMP Playground",
"url": "https://playground.amp.dev/"
}
]
}
基本的には、<amp-list>
内でレイアウトとエンドポイントを指定し、<template type="amp-mustache">
内でどういうふうにレンダリングするかを決めます。
amp-mustache
では、以下のように変数を利用できます。
- ただの変数
{{変数名}}
<!-- Using template tag. -->
<template type="amp-mustache">
Hello {{world}}!
</template>
- 変数が存在していればレンダリング
{{#section}}{{/section}}
<!-- Using template tag. -->
<template type="amp-mustache">
{{#world}}
Hello {{world}}!
{{/#world}}
</template>
- 変数が存在していなければレンダリング
{{^section}}{{/section}}
<!-- Using template tag. -->
<template type="amp-mustache">
{{^world}}
No World!
{{/#world}}
</template>
JSX内でのテンプレート
JSX内ではこれらのテンプレートは
<template type="amp-mustache">Hello {"{{world}}"}!</template>;
のように利用できます。
実装方針
これらのことから、/api/otherarticles
のようなエンドポイントを作成し、そこから
[
{
"title": "test post",
"url": "/posts/test"
}
]
のようなものを返すことにします。
そうするとamp-list
の実装は
<amp-list
width="auto"
height="200"
layout="fixed-height"
src={`/api/otherarticles`}
items="."
>
{/* @ts-ignore */}
<template type="amp-mustache">
title={"{{title}}"}
url={"{{url}}"}
</template>
</amp-list>;
のようにすればよいです。
APIの実装
Next.jsのAPIは、pages/api/
下にts
などのファイルを作ればエンドポイントが作成できます。
pages/api/otherarticles.js
export default function handler(req, res) {
const articles = {
title: "test post",
url: "/posts/test"
}
res.status(200).json(articles)
}
のような感じです。
実際の実装では、Next.jsで作ってみたブログに検索機能を導入するのような感じでキャッシュを作成しておいて、そのキャッシュを参照してランダムな配列から規定数のファイルを取り出しています。このブログのその部分の実装はgithubにあります。