Nuxt.jsのuniversalモードをFirebase Hostingというホスティングサービス上で動作させようとしたときにかなりハマったので、そのときの内容をまとめておこうと思います。
まずは、Nuxtのモードについて簡単に振り返ってみます。

NuxtJSのモードについて

Nuxt.jsには、Universal、Single Page App、静的ページの3種類のモードがあります。Universalモードは、SSRとよばれているサーバサイドレンダリング、SPAは、シングルページアプリケーション、静的ページは、昔から利用されていた静的ページです。

Universalモード

サーバサイドレンダリング(SSR)を行うモードです。サーバ側でjavascriptをレンダリングしてHTMLの出力をします。

Single Page Appモード

Singleページは、クライントサイドでjavascriptをレンダリングする仕組みです。

Universalモード(SSR)で動作させるには、サーバサイドでもレンダリングを実行する必要があります。Firebase Hostingを利用した場合にも、このレンダリング部分が問題になるのですが、こちらの方法については、すでにCloud Functionsと組み合わせてやるのが一般的になっているようですので、今回もその方法を採用します。

NuxtJS(Universal)のFirebaseHostingの概要

ビルドコマンド(yarn build)でNuxtJSをビルドするとClient向けロジック、Server向けロジックの2つが生成されます。この2つのロジックと/Staticにある画像などは、Clinetサイドでレンダリングされるので、クライント側(Hosting)、Serverのロジックについては、cloud functionsとしてnode runtime上で動くような形でデプロイします。
リライトルールで、リクエストをcloud functionへ転送して上げて、サーバサイドのロジックのレンダリングを行います。下記に簡単な概要図を記載します。

実現しようとしていたこと

認証認可の仕組みをfirebase Authenticationを利用してクッキーに保存した情報をサーバサイドで保存したクッキーを取り出し、ユーザ情報を復元して、認証許可判定に利用するという流れを想定していました。環境の制約は、以下の通りです。

  • NuxtはUniversalモード
  • 認証許可済みの場合しか表示しないページがある
  • 認証許可を行い、未認証の場合には、ログインページにリダイレクトする

認証ルートとログイン状態の復元

Storeを利用した認証ルートについては、公式ページで説明されていてそちらを参照にして実装します。NuxtJSでは、ページのリロードを行うとStoreの状態が初期化されてしまします。nuxtServerInit()というメソッドで状態を復元を行います。公式で紹介されているように下記図を参照するとnuxtServerInit()がいつ呼ばれるのかも記載されています。

Incoming Mesageはページロードなどのユーザからのページ更新要求で実行されるので、状態の復元を行うためのロジックとして利用できます。ページ内の遷移では、このロジックが実行されない点とサーバサイドで実行されるという点についても注意が必要です。余談ですが、静的サイトを作成するgenerateを利用した場合、nuxtServerInit()はビルド時にコールされます。

安易な方法の一つとして、思いつくのは、ログイン状態をlocalStorageで管理するという方法です。nuxtServerInit()は、サーバサイドのロジックのため、localStorageを参照することができません。今回は、cookieを利用する方法を選択しました。これで状況の準備が出来ましたのでハマったことの紹介です。

ハマったこと

cookieのキーがFirebaseHosting、Cloud Functionsを利用して、読みだそうとすると書かれていないという現象がありました。access_tokenのような名前をつけて
firebase serveを利用してローカルでhosting、cloud functionsの連携確認を行い問題なくdeployを行い、いざ実行すると動かないという状況です。驚いたのは、localとpublicで挙動が違うという点でした。

解決

ドキュメントを何度かよんで以下の記述を見つけました。

ここに記載されている通り、アプリ側へ到達するセッションは、__sessionのみということです。これでようやく解決です。環境に依存する問題はなかなか厄介です。ネット上で多くの情報があるNuxtJSを利用したFirebase Hostingの話題でしたが、__session制約については、なかなか見つけることができず苦労しました。