2018/10/25
nuxt SSR + 都度デプロイなしでブログをFirebase配信する

 実は私、ブログを作るのが趣味なんです。ということで表題の通りです。

 延々と解説してもしょうもない話になるのでGitLabにリポジトリ出してあります。デザイン? そういうのは後でやるからいいの!

いいところ

 Nuxtでブログをやろうという場合、おそらく現状で多いのは「マークダウンを食わせて、nuxt generateでファイルを出力する」というアプローチだと思います。僕もこのフローを使ってGatsbyとかVuePressでブログを作ったことがありますし、何も問題なく作れます。配信方法の選択肢も豊富で、実際かなりいいです。

 ただ、敢えてこのアプローチの問題点をあげるとすれば、それはやはり毎回ビルド走るのがなんか嫌という部分でしょう。マークダウンで原稿を書き、何らかの方法でCIを動作させ、静的サイトが生成されてデプロイされるのをいちいち待つことになります。それで別に何も支障はありませんが、なんか嫌ですよね? 記事を追加したいだけで、別にサイトのデザインとか変わってないのに、それで毎回ビルドするなんて何やらしっくりきません。嫌ですね。

 これに対する1つの答えが「SPAモードでデプロイしてSSRを諦める」というもので、これまた実際いいんですね。シンプルですし、ほとんどの場面で支障なく動きます。ただこちらには「SPAを理解しないクローラーにメタタグを渡せない」という割と致命的な問題があります。みんな大好きツイッターで、URLをツイートしたのにカードが出ないなんてなんか嫌ですよね? 個人的にはSEOも検索エンジンもゴミだと思っていますが、それはそれ、これはこれで、渡すべき値を渡せないというのは嫌なものです。

 ということでSSRをやりましょう。Firebaseならほぼ確実にタダみたいなもんですし。

ハマったとこ

 忘れないうちにメモ。Nuxt + Firebase + SSRはあんまり知見がないぽいので。

package.jsonの依存関係がだるい

 考えてみると当たり前なんですが、nuxt buildの出力結果にはnpmモジュールのバンドルとか含まれていません。つまりSSRをやるときには必要なものが全て実行環境のnode_modulesに入ってないとダメです。SSRをする関数のために全部入りpackage.jsonが必要になるわけですね。

 これがややこしいのは、親切なエラーが出ない(少なくとも今回は見た覚えがない)ので、理屈を知らない限り原因が全然わからんということです。なんか真っ白い画面が出てるー、キレーイ… ってなります。なりました。

 結局、ファイルが2つあるから間違えるのだということで、リポジトリ全体で1つのpackage.jsonを使うのが一番マシだろうと思います。

buildDirがだるい

 SSR実行用にbuildDirを設定することがあると思いますが、あのパスは仕様上「プロジェクトルートからの相対パス」になります。そしてここにいう「プロジェクトルート」は原則としてカレントディレクトリを意味するので、要するにbuildDirtとは「カレントディレクトリからの相対パス」を意味します。関数のあるファイルからの相対パスではありません。なのでfunctions/index.jsとかfunctions/src/index.jsとかディレクトリ構造をいじり始めると一瞬で訳が分からなくなり、ビルド成果物を別ディレクトリに集合させるとさらに混乱が発生します。「ローカルでは動くのにサーバーではダメ」みたいなことが(真っ白画面で)頻発するので心をやられることは確実です。

 例えば私のリポジトリではssrというbuildDirを指定していますが、これは「nodeコマンドを叩いたカレントディレクトリにあるssrというディレクトリ」という意味になります。正直、これは仕様が不親切じゃないかという気もするのですが。

buildDirの中身が謎

 諸説ありますが、nuxt build実行により生成される.nuxtの中身をそのまんま入れておく必要がありそうです。

静的ファイルの配信が手間

 ビルド結果のうち、faviconだのJSだの画像だのはSSRに関係がなく、無駄に関数を通したりせずそのまんま配信するべきでしょう。実はまだfaviconとか対応できてないんですが、これ自体は簡単な話で、然るべきディレクトリ構造を偽装してそのまんまアップロードする必要があります。リポジトリ見てね。

 実際このリポジトリの処理でも、ビルド設定でassetsというパスを指定したうえ、ビルド後に.public/assetsなる胡散臭いディレクトリ構造をでっち上げ、それをそのまんまアップロードしています。21世紀にあるまじき涙ぐましさですが、これで動きます。

ネットワークの規制

 CMS叩きに行くのは多分、有料青天井プランじゃないと無理です。ほぼ確実に無料で収まると思いますが、なんか怖いのでAppEngineから上限設定して使いましょう。

これからやること

 とりあえずこの下に開発用JSONがそのまんま出ているので、それ消します。

追伸

 消しました。

ここにサブメニューを作る(つもり)