Nuxt.js静的サイトモードのfallbackのSPAモードとnuxtServerInit

大前提として、nuxtServerInitというAction名のとおり、これはサーバサイドでしか実行されない。
静的サイトモードだと、設定によるけどgenerateコマンドの実行時に呼ばれる。

そしてfallbackのSPAモード。これは動的に扱いたいroute用の機能だけど、このSPAモード用のhtml(200.htmlとか404.htmlとか)の生成時にはnuxtServerInitは呼ばれない。

SPAモードではnuxtServerInit呼ばれない、という仕様なんだから確かにそのとおり。なんだけどこれを完全に失念しててSPAモードで表示していた一部ページと、そこから遷移した各ページで一部データにアクセスできない、という状況が生まれてしまっていた。

解決する方法はいくつかあるけど、今回はSPAモードでもnuxtServerInitを呼ぶ方法を採用した。
実装は簡単。

まずはStateに初期化済みかどうか判定できる値を用意する。initialized: booleanみたいな値を用意するのでもいいだろう。

次にpluginを追加する。単純に、Stateが初期化済みでなければnuxtServerInitを実行する。
resとかreqとかcontextの一部の値はクライアント側ではアクセスできないので、そこは注意が必要。

typescript
// ~/plugins/init.client.ts
import { Context } from '@nuxt/types'
import { RootState } from '~/store'

export default async function ({ app, store }: Context): Promise<void> {
  if (!(store.state as RootState).initialized) {
    await store.dispatch('nuxtServerInit', app.context)
  }
}

nuxt.config.tsのplugin設定はこんな感じに

typescript
plugins: [
    ...,
    { src: '~/plugins/init.client.ts', mode: 'client' },
]

mode: 'client'が重要。nuxtServerInitはサーバサイドでは普通に呼ばれるので、SPAモード(=ブラウザ側)でのみ処理されればいい。

参考