🪤

NuxtのSSGのgenerateの改善~payloadちゃんと使えてますか?~

2021/09/20に公開

Nuxt の generate の改善を職場ですることがあったので、そこで学んだことを備忘録的に書いてきます。

環境

nuxt v2.15.7

Qiita の API について

Qiita api を使って実際にやってみます。
(Zenn に記事書いてるのに Qiita で申し訳ないですが、サンプルにちょうどよかったので。)

Qiita の API のドキュメントはこちら

一覧の取得のドキュメントはこちら

特定の記事の取得のドキュメントはこちら

100 件の記事を取得するには以下のような感じす。
https://qiita.com/api/v2/items?page=1&per_page=100

題材

QiitaAPI で取得した記事のタイトルの一覧画面

QiitaAPI で取得した各詳細記事のタイトルのみの画面

というすごくシンプルなものです。

axios を使う

axios の install

$ yarn add axios

API のを叩くために axios を利用します。

Nuxt の通常バージョンで generate する

nuxt-link にあるものは自動でビルドしてくれるようです。
参考ドキュメント

まずは以下のようなソースでビルドしてみます。

pages/post/index.vue
<template>
<div>
  一覧
  <ul>
    <li v-for="post in posts" :key="post.id">
      <nuxt-link :to="`/post/${post.id}`">
      {{post.title}}
      </nuxt-link>
    </li>
  </ul>
</div>
</template>

<script>
import axios from 'axios';
export default {
  async asyncData({app}) {
    return await axios.get('https://qiita.com/api/v2/items?page=1&per_page=100',
      {
        headers: {
          Authorization: `Bearer ${app.$config.token}`,
        }
      }
    )
    .then(response => {
      return {
        posts: response.data
      }
    })
  },
}
</script>

pages/post/_id.vue
<template>
<div>
  {{post.title}}
</div>
</template>

<script>
import axios from 'axios';
export default {
  async asyncData({app,params}){
    return await axios.get(`https://qiita.com/api/v2/items/${params.id}`,
      {
        headers: {
          Authorization: `Bearer ${app.$config.token}`,
        }
      }
    ).then(response=>{
      return {
        post: response.data
      }
    })
  }
}
</script>

503 エラーになる

この状態でyarn generateをすると、下記のように 503 エラーが出ます。

各記事ページの生成時にも API のリクエストがいきますし、リクエストの間を空けないためそうなっているのでしょう。

interval を使います。
interval プロパティのドキュメント

nuxt.configinterval:100 を指定します。

nuxt.config.js
export default {
  //他のところは割愛
+ generate:{
+   interval: 100,
+ }
}

generate の結果です。

一応ソースコードはこちらにあげてます。

payload を使う

nuxt-link が貼られている path はnuxt.configgenerateプロパティに記載してくても、ページ生成はされます。
参考

ただ、payloadを使うためには、generateプロパティに記載する必要があります。

payload とは

詳細記事のルーティングを作るために API にアクセスしたときに、
そこで 100 件分の記事のデータを取るなら、
そのデータを payload に入れて、
各記事のページでも payload を使うことで API のアクセスを減らせます。

nuxt.config に以下のようなコードを追記します。

nuxt.config.js
+ import axios from 'axios';

export default {
  generate:{
+    async routes(){
+     const posts = (await axios.get('https://qiita.com/api/v2/items?page=1&per_page=100',
+        {
+          headers: {
+            Authorization: `Bearer ${process.env.TOKEN}`,
+          }
+        })
+      ).data

+      const postRoutes = posts.map(post=>{
+        return{
+          route:`/post/${post.id}`,
+          payload:post
+        }
+      })
+      return [
+        {
+          route:"/post",
+          payload: posts
+        },
+        ...postRoutes
+      ]
+    }
  }
}
pages/post/index.vue
<template>
<div>
  一覧
  <ul>
    <li v-for="post in posts" :key="post.id">
      <nuxt-link :to="`/post/${post.id}`">
      {{post.title}}
      </nuxt-link>
    </li>
  </ul>
</div>
</template>

<script>
import axios from 'axios';
export default {
  async asyncData({ app, payload }) {
    //payloadを使う
    const posts = payload !== undefined ? payload
      : (await axios.get('https://qiita.com/api/v2/items?page=1&per_page=100',
        {
          headers: {
            Authorization: `Bearer ${app.$config.token}`,
          }
        }
        )).data
    return { posts }
  }
}
</script>

pages/post/_id.vue
<template>
<div>
  {{post.title}}
</div>
</template>

<script>
import axios from 'axios';
export default {
  async asyncData({app, params, payload}){
    //payloadを使う
    const post = payload !== undefined ? payload
      : (await axios.get(`https://qiita.com/api/v2/items/${params.id}`,
        {
          headers: {
            Authorization: `Bearer ${app.$config.token}`,
          }
        }
        )).data
    return {post}
  }
}
</script>

今回の場合であれば、payload によって API のアクセスは 1 度で済むようになったので、
interval もセットする必要がなくなりました。

generate にかかる時間も速くなりました。(22.02→12.27)

ここまでのソースはこちらです

payload は dev では undefined になる

yarn dev では payloadundefined になるので、注意する必要があります。

payload 自体の動作確認はyarn generate してから yarn start する必要があります。

まとめ

Nuxt の SSG の generate 時には payload を上手く使うことで、不要な API のアクセスを減らすことができます。
もし、generate に時間かかっているなら、不要にデータを取得してないか見直してみるといいかもしれません。

Discussion