メインコンテンツまでスキップ

Nuxt.jsのSSGで、ページの生成時にAPIリクエストを減らす方法はありますか?

nuxt.config.jsのgenerateプロパティにroutesのオプションを設定することで、ページのリクエストを減少させることが可能です。

今回は一例として、記事一覧ページと記事詳細ページがあるページを想定し、記事詳細ページにてAPIリクエストを減少させる方法を説明します。

ページのリクエスト減少させるサンプル

ページリクエストを減少させるためのサンプルコードをご紹介します。
今回は、大量に存在するslugのコンポーネントでasyncData()を利用し、APIからデータを取得していくようなケースを想定します。
その場合、SSG時にコンポーネントの数の分だけAPIアクセスしてページを生成していくことになります。

しかしながら、まず一箇所で集中してデータを取得し、取得したデータをそれぞれのコンポーネントに配布していく方法を取ることで、対象のAPIアクセスを削減できる場合がありより効率的になります。
例えば、記事一覧ページと記事詳細ページを作成するようなケースを想定します。ファイル構成やソースコードは以下のように作成したとします。

記事一覧ページ
<template>
<div>
<nuxt-link
v-for="topic in topics"
:key="topic.topics_id"
:to="`/topics/${topic.topics_id}`"
>
{{ topic.subject }}
</nuxt-link>
</div>
</template>

<script>
// TopicsList page
// /pages/topics/index.vue
export default {
async asyncData ({ $axios }) {
return { topics: (await $axios.$get(`${process.env.BASE_URL}/rcms-api/1/topics/`)).list }
}
}
</script>
記事詳細ページ
<template>
<div>
<h1 class="title">{{ topic.subject }}</h1>
<div class="post" v-html="topic.contents"></div>
</div>
</template>

<script>
// TopicsDetail page
// /pages/topics/_slug.vue
export default {
// calls 100 times on static generation if the topics contains 100 items
async asyncData ({ $axios, params }) {
return { topic: (await $axios.$get(`${process.env.BASE_URL}/rcms-api/1/topicsdetail/${params.slug}`)).details }
}
}
</script>

上記ソースコードでは、仮に100件の記事が存在する時には100回分の記事詳細APIへのリクエストがされます。
しかしながら、実際には記事詳細はtitlecontentsしか利用していません。
この場合、これらデータは記事一覧で取得したデータ内に含まれているため、そもそも記事詳細のAPIをリクエストする必要がありません。

routesのオプションを設定し、ページのリクエストを減少させる

より効率的にするため、記事一覧用データを1回だけ取得し、そのデータを各コンポーネントへと配備していくよう修正します。

nuxt.configの修正

まずはnuxt.config.jsを修正します。以下のように修正してください。

require('dotenv').config();
const { BASE_URL } = process.env;
import axios from 'axios';

module.exports = {
generate: {
async routes() {
const topicsList = (await axios.get(`${process.env.BASE_URL}/rcms-api/1/topics`)).data.list;
return topicsList.map((topic) => ({
route: `/topics/${topic.topics_id}`, // a path of TopicsDetail
payload: topic // destributes topic data to the target component (TopicsDetail)
}))
}
},

記事詳細ページの修正

次に、記事詳細ページを以下のように修正します。

<template>
<div>
<h1 class="title">{{ topic.subject }}</h1>
<div class="post" v-html="topic.contents"></div>
</div>
</template>

<script>
// TopicsDetail page
// /pages/topics/_slug.vue
export default {
- async asyncData ({ $axios, params }) {
- // calls 100 times on static generation if the topics contains 100 items
+ async asyncData ({ $axios, params, payload }) {
+ // conveys the topic data as `payload`
+ if (payload) {
+ return { topic: payload };
+ }
+ // now that we don't use bellow any longer on static generation, but remain it just in case of local dev
return { topic: (await $axios.$get(`${process.env.BASE_URL}/rcms-api/1/topicsdetail/${params.slug}`)).details }
}
}
</script>

この修正により、SSGにおける記事詳細ページではリクエストが0回となり、100回分の記事詳細へのリクエストがされないようになりました。
そのため、結果的にSSGによる記事生成処理が短縮されることになります。

ヒント

ローカルで確認する際は、ターミナル上でnpx nuxt generate && npx nuxt serveを実行してください。

備考

nuxt.config.jsのrouteについては、Nuxt公式ドキュメント -> routesについてをご参照ください。


サポート

お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。