Nuxt.jsでAPI通信なしの静的ファイルを書き出す

Nuxt.jsのComposition APIuseStatic() メソッドを使用して、API通信しない静的ファイルを書き出しできるかを試してみました。

経緯

開発案件でマークアップを担当する際に、開発リポジトリとは別にデザインチーム用のGitを作成するケースは多いです。
静的なHTML/CSSファイルを開発チームの方に組み込んでいただくフローになりますが、確認含めたコミュニケーションが煩雑になることもあったりします。

そのため開発のリポジトリ上で直接マークアップできたほうがいいとは考えているのですが、ディレクターやデザイナーに向けたデザイン内部のレビューが、プロジェクトによっては開発環境にデプロイされてからでないとできない、などいくつかの懸念点もあります。

そこで、ICSさんの API通信一切なし!Nuxt Composition APIで作る完全静的サイト という記事を読んで、API通信しない静的書き出しが可能であればS3にアップすれば前述の懸念は少なくなるかなと思い、この記事を参考に開発環境下ではAPI通信するサイトを静的書き出しできるのかを試してみました。

どうやるのか

Composition APIと非同期処理メソッド

前述のNuxt.jsのComposition APIuseStatic() メソッドを使用します。

まずComposition APIuseStatic() が何かをざっくり解釈すると、

  • Vue2まで使われていたのはOptions API
    • Nuxt.jsでも2.13から asyncData(), fetch() メソッドを使用してデータ静的化ができた
  • Vue3からComposition APIが推奨化された
    • Nuxt.js用に拡張されたNuxt Composition APIとしてリリースされた
    • Nuxt Composition APIには asyncData(), fetch() メソッド が用意されていない
    • 代わりに useAsync(), useFetch(), useStatic() の3つの非同期処理メソッドが用意されている

という流れになるようです。

Nuxt Composition APIでの静的化

useAsync(), useFetch(), useStatic() の3つの非同期処理メソッドの違いについても前述のICSさんの記事が詳しいですが、ざっくり解釈すると

  • 完全静的化で使用できるのは useFetch(), useStatic()
    • useFetch() メソッドはSmart Prefetch機能がある
      • Smart Prefetch機能とは、ブラウザの表示領域に <nuxt-link> を見つけたらそのリンクをブラウザが先読みする機能
    • useStatic() は2回目以降、初回でファクトリー関数を実行したAPI通信内容を保存する
      • ファクトリー関数とは、オブジェクトを返す関数のこと
      • サーバーサイドレンダリングにおいては、2回目以降のアクセスでは useStatic() の方が高速に表示できる

ということで、分かるような分からないような、メリット・デメリットはありますよ、ということだと解釈します。

API通信一切なし!Nuxt Composition APIで作る完全静的サイト より

今回はSSRのサイトを静的化したほうが目的に沿いそうなため useStatic() を使用します。

やってみる

プロジェクト作成

create nuxt app でつくります。
Node.jsのバージョン:14.13.0

$ yarn create nuxt-app nuxt-composition-api-sample

Nuxt Composition API と Axios を使うためにパッケージをインストール。

$ yarn add @nuxtjs/composition-api @nuxtjs/axios

nuxt.config.js にそれぞれ追加。

...
  buildModules: [
    ...
    '@nuxtjs/composition-api/module' // 追加
  ],

  modules: [
    ...
    "@nuxtjs/axios" // 追加
  ],
...

同じく nuxt.config.js にgenerate時のターゲットを設定。

  target: 'static'

ローカル起動してみる。

$ yarn dev

useStatic() を使う

components/Tutorial.vue を適当にリネームします。
今回は記事通り Nuxt.jsの山のAPI を使うので、Mountains.vue としました。

CSS除いたコードは下記のような形になります。

<template>
  <ul>
    <li v-for="item in data" :key="item.title">
      <h1>{{ item.title }}</h1>
      ... 省略
    </li>
  </ul>
</template>

<script>
import {
  defineComponent,
  useStatic,
  computed,
} from '@nuxtjs/composition-api'

import axios from 'axios'

export default defineComponent({
  setup() {
    const param = computed(() => 'hoge')
    const keyBase = 'fuga'
    const data = useStatic(
      async (param, key) => {
        console.log(param) // hoge
        console.log(key) // fuga-hoge
        const mountains = await axios.get(`https://api.nuxtjs.dev/mountains`)
        return mountains.data
      },
      param,
      keyBase
    )
    return { data }
  }
})
</script>

useStatic() の引数は下記のようになり、動的ルーティング(_id.vueなど)もできるようになっています。

API通信一切なし!Nuxt Composition APIで作る完全静的サイト より

できた画面は下記

generate する

yarn generate をしてみると、dist/ に 山のデータが入った fuga-hoge.json があります。

dist/ のHTMLをブラウザで見てみるとこのJSONを読みに行ってくれています。

所感など

記事通り試す程度はできましたが、動的ルーティングで試したり、もう少し useFetch() との違いなどを理解できればもっと使えるような感じがします。
単純にAPIから何かを表示するだけのサイトは問題ないですが、DBやセッションが絡むサイトは難しそうな感じもしますね。。

Composition APIは機能が多く書き方もOptions APIとは結構変わっていたので、また触っていきたいなと思いました。

ほか参考にしたサイト