Programming / Travel / Liquor

Nuxt generate時に動的ルーティングページを生成する方法&payloadでgenerate高速化

Nuxt

Nuxt generateする時に動的ページを生成する方法と、generateの高速化方法について。

動的ルーティングページはgenerate対象外

Nuxt.jsではpageディレクトリ配下で、アンダースコアプレフィックスを付与したディレクトリまたはフォルダを作成することで、それが固定のパスではなく動的なルーティングとして定義することができます。

>> 動的なルーティング

こういった動的ルーティングはNuxtからしたらどのようなパスがあるかわからないため、generate時に静的ページを生成してくれません。

そのため、generate時に動的ルーティングで使われるパスを教えてあげる必要があります。そうすることでそのパスに従ってNuxtが静的ページを生成してくれます。

※ 静的ページがないと何も対処しない場合リロードした際に404エラーとなります。

動的ルートを指定する

動的ルーティングパスの指定はnuxt.config.jsで定義します。

generateプロパティのroutesオプションで動的ルートが定義された配列を生成して返しています。

export default {
  generate: {
    routes: async () => {
      const api = await initGenerateApi();
      const entrys = await api.query(Prismic.Predicates.at("document.type", "entry"));
      return entrys.results.map(entry => {
        return {
          route: `/entry/${entry.uid}/`,
          payload: entry
        };
      });
    }
  }
}

initGenerateApi はprisnicのAPI初期化用のため気にしないでください。

prismic APIのクエリを使用しているためわかりずらいかもしれませんが、やっていることは以下の通りです。

  1. prismicAPIで記事データ(配列)を全件取得する
  2. 記事データ配列から1記事ずつ取り出す
  3. 記事のuid(urlに使用)を使ってgenerate用パスを生成

payloadに記事データをセットしているのは後述の高速化のためです。

以上の処理でgenerate時に動的ルーティングぺージの静的ページを生成してくれます。entryパス以外にも動的ページを利用している場合は同様の処理を追加してあげるだけです。

基本的には上記の処理の流れでOKなのですがあくまでも本ブログの実装なので、APIクエリ等はサイトの構成に合わせて変更が必要になります。

なお、以下の記事にある通り、本ブログではNuxtのtrailing slashの設定を有効としているため、上記のroute生成の箇所で末尾のスラッシュを忘れないように追加します。

Nuxt generateの高速化

前述の通り、動的ルートの静的ページ生成のために、generate時にAPIを実行して記事データを取得しますが、通常はこのルーティングのためだけに使われるデータのため、uidを取得した後は破棄しています。

そのため、動的ページで再び記事データをフェッチしないといけなくなります。これは単純に考えて、無駄なAPIコールでありgenerate時間も増えてしまいます。

これを防ぐために、generate時のAPIで取得した記事データを動的ページのコンテキスト(payload)へ渡してあげるようにします。(上記nuxt.config.js参照)

動的ページではpayloadを利用することで無駄なAPI実行がなくなり、APIコールの節約・時間短縮になります。

async asyncData({ app, params, error, req, payload }) {
    try {
      // payloadがあればそれを利用
      if (payload) {
        return { entryData: payload };
      }
      const api = await app.$initApi(req);
      // uidで個別エントリを取得
      const entry = await api.getByUID("entry", params.uid);
      return {
        entryData: entry
      };
    } catch (e) {
      error({ statusCode: 404, message: "Page not found" });
    }
  }
}

おわりに

今回の方法はページが少ないうちはあまり効果がないかもしれないですが、ページが増えるほど効果が顕著になってくるはずです。

CMSによってはAPI実行回数の制限が厳しいところもあるので、こういうところを気にしていかないとですねー

About
K

旅行とお酒、そしてプログラミングが大好きなエンジニアです。

バックエンド、言語としてはJava(Spring FW)・Cが専門ですが、最近はVue/Nuxtをはじめとするフロントエンドまわりも勉強中。

旅行は国内・海外問わず、海外旅行は現在12か国、国内は色々。東南アジアの旅行ならカンボジアが大好き(3回ほど渡航)

お酒はビール・ウイスキー・日本酒があればOK。

Portfolio

QT Visualizer

Portfolio Site

プライバシーポリシー

Frontend by Nuxt & Vuetify / Contents by Prismic.io

© 2019 K note.life