【Next.js】SSG を利用したサイトアーキテクチャ
概要
本記事は、Next.jsのSSGを利用した技術とサイトの設計指針についてまとめました。
※ 私自身、Next.jsについてはまだ勉強中で、その備忘録として書いています。
SSG(Static Site Generation|静的サイト生成)
Next.jsでは、SSG(Static Site Generation|静的サイト生成)という技術が標準サポートされていて、それを使用することが推奨されています。SSGを使用すると、SEOに有利で、高速に表示されるサイトを作ることができます。
また、SSGを利用してAPIなど外部との通信が発生する処理(時間のかかる処理)を、サイトのビルド時に行い(Pre-fetch)、そのデータを埋め込んだHTMLをあらかじめサーバー側で生成することができます。
詳しく知りたい方は、公式ドキュメントを参照してください。英語ですが図説されているのでわかりやすいです。
Pre-rendering and Data Fetching
日本語がいい!という方は、以下の動画シリーズがおすすめです。
Deploy Hooks
Next.jsを開発しているVercel社は、Hostingサービスも提供しています。
このサービスでは、GitHubに連携してリポジトリ(mainなど)の更新に応じてリビルドする機能や、API経由でリビルドするDeploy Hooksが提供されています。
ISR(Incremental Static Regeneration|段階的な静的サイト生成)
ユーザーがサイトに訪れたときにサイトをリビルドして、次に訪れたユーザーに最新のサイトを提供する機能です。
① ユーザーAが、Vercelサーバーにリクエストを送ります。
② Vercelサーバーは、レスポンスとしてホスティングされたサイト(HTML)を返します。
③ ②と同時に、Vercelサーバーは、更新のあるページ(ISRを指定したページ)だけをリビルドします。
④ ユーザーBが、Vercelサーバーにリクエストを送ります。
⑤ Vercelサーバーは、レスポンスとして③で更新したサイト(HTML)を返します。
revalidateは更新頻度で、コード内でこれを指定することでISR機能を使うことができます。
上図では、ユーザーBは最新のサイトを閲覧できますが、ユーザーAは古いサイトを閲覧することになります。このことから、ISRは、閲覧回数が多いサイト向けの機能です。
revalidateを指定することで、高頻度のサイトアクセスによる過剰な更新を防ぎ、サーバー負荷を減らします。(ゲームでいうところのスキルのクールダウンみたいな感じです)
コード例
export const getStaticProps: GetStaticProps = async () => {
const tasks = await getAllTasksData();
return {
props: { tasks },
revalidate: 3
};
};
getStaticProps
のreturnに、revalidateを指定することで、ISRに対応させたページにします。
Client side Fetching(CSF)
クライアントサイドで、効率よくAPIでデータを取得する方法として、SWRがあります。
キャッシュデータを使うことで過度なAPIリクエストを防ぎ、素早くサイトを表示させます。
これを使って何が嬉しいのかというと、ISRだけでは、ユーザーAは最新のサイトを閲覧できませんでした。
そこで、このSWRと組み合わせることによって、ユーザーAも最新のサイトを閲覧することができます。
下図は、SSG + ISR + CSF(SWR)を組み合わせた例です。
① 開発者がサイトをデプロイします。
②②´ Vercelサーバーは、SSGのPre-fetchによりビルド時にAPI経由でデータを取得します。
③③´ ユーザーAがサイトにアクセスします。
③″ クライアントサイドで、API経由で最新のデータを取得します(Client side Fetching)。
④④´ ③のリクエストをトリガーにして、ISRによってリビルドされます。このとき、②´同様にAPI経由でデータを取得します。
※③″と④´でAPIからデータを取得するタイミングはほぼ同じなので、同じでデータになるはずです。(秒単位で更新されるデータの場合は差異が生まれるかもしれません)
⑤⑤´ ユーザーBがサイトにアクセスします。
⑤″ ③″同様、クライアントサイドで、API経由で最新のデータを取得します(Client side Fetching)。
※ユーザーAがサイトに訪れてから、ユーザーBが訪れるまでに、サーバーのデータが更新されていなければ、⑤´の内容と⑤″で取得する内容は同じになります。
コード例
const fetcher = (url: string) => fetch(url).then<TaskType[]>(res => res.json());
type PropsType = {
tasks: TaskType[];
};
const TaskPage: VFC<PropsType> = ({ tasks }) => {
const { data, error } = useSWR(`${process.env.NEXT_PUBLIC_RESTAPI_URL}/api/list-task/`, fetcher, {
initialData: tasks, // ― 2
revalidateOnMount: true // ― 3
});
// 以降、得られた data を使った処理
・・・
}
export default TaskPage
export const getStaticProps: GetStaticProps = async () => {
const tasks = await getAllTasksData(); // ― 1
return {
props: { tasks },
revalidate: 3 // ― 4
};
};
① SSGのPre-fetchで、サーバーサイドでAPIデータを取得します。
② useSWR
のオプション、initialData
にサーバーサイド取得したAPIデータ(tasks)を渡します。
これによって、クライアントサイドでデータが取得できるまでは、サーバーサイドで取得したデータを表示させます。
※このとき、APIデータに更新があると、古いデータ → 新しいデータとレンダリングされるので一瞬だけ古いデータが表示されます。
③ useSWR
のオプション、revalidateOnMount
を指定することで、コンポーネントがマウントされたときに必ずデータを取得するようします。
④ ISRに対応させることで、次にサイトを表示したときに、②で発生していた古いデータが一瞬だけ表示される現象が発生しないようにします。
サイト アーキテクチャ
これらの技術を使うことで、API経由で取得するデータの更新頻度、APIの使用制限、サイトのアクセス頻度に併せてサイトを設計することができます。
※ 以下のモデルは、あくまで一例です。
手動でリビルドする
API経由で取得するデータの更新に併せて、サイトを手動でリビルドします。
条件・状況
・API経由で取得するデータの更新頻度が低い場合(半年に1回、不定期など)
・APIの使用制限が厳しい場合(1時間あたりのリクエスト回数が決まっている、リクエスト回数に応じて料金が発生する)
・サイトのアクセス頻度が低い場合
Deploy Hooks を使う
Deploy Hookに、Cloud Functions(Cloud Functions for Firebase、 AWS Lambda など)を組み合わせることで、定期的に自動でリビルドするようにします。(毎日24:00にリビルドするHookを作る)
条件・状況
・API経由で取得するデータの更新頻度がそこそこの場合(数周間に1回、1日に1回など)
・APIの使用制限が厳しい場合(1時間あたりのリクエスト回数が決まっている、リクエスト回数に応じて料金が発生する)
・サイトのアクセス頻度が低い場合
ISR を使う
ISRの項目で紹介した設計を使います。
条件・状況
・API経由で取得するデータの更新頻度が高い場合(数時間に1回、数分に1回など)
・APIの使用制限がそこそこ
厳しい場合(1時間あたりのリクエスト回数が決まっている、リクエスト回数に応じて料金が発生する)
・サイトのアクセス頻度が高い場合
ISR + Client side Fetching を使う
Client side Fetchingの項目で紹介した設計を使います。
条件・状況
・API経由で取得するデータの更新頻度が高い場合(数時間に1回、数分に1回など)
・APIの使用制限がゆるい場合(自社製のAPIサーバーを使うなど)
・サイトのアクセス頻度がそこそこ
高い場合
まとめ
Next.js 面白い。
参考
この記事は、以下のコースの受講に伴って、備忘録としてまとめました。
もっと詳しく知りたい方は、是非受講してみてください。
Author And Source
この問題について(【Next.js】SSG を利用したサイトアーキテクチャ), 我々は、より多くの情報をここで見つけました https://qiita.com/nemutas/items/523f387877215b0cfc1f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .