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
制約については、なかなか見つけることができず苦労しました。