Rso's Jotter

日々の開発の知見のメモやその他雑記

Nuxt.js(SPA), Firebase Hosting, Cloud Function でOGP対応してみた

以前、内輪の開発合宿で Quizhub というサービスを作ってみたんですが、 OGP対応したいよねという話が出てきました。

このサイトはFirebase Hostingを使用しているので、Nuxt.js の SSRは使用できません。 対策をググったらいろいろ出てきたので、まあできるだろうと思ったら、思ったより手こずってしまったのでその内容をメモしておきます。

OGPとは?

あまり詳しく書きませんが「Open Graph Protocol」の略で、これに沿った形式でmetaタグを書いてやると、 それに対応しているサービスでURLを貼ると、そのタイトルや概要、画像などがきれいに表示され、見やすくなります。 Twitter, LINE, SlackなどでURLを貼るとぺろっとその内容がでてくるアレです。

SPAの問題点

SPAはビルドした時点でファイルが生成されるので、QuizHubでいうとクイズ詳細画面で、クイズタイトルや概要、使用されている画像をmeta tagにいれることができません。

対応内容

内容はここのブログの方法を参考にさせていただきました。というか、ここの内容の2番煎じです。

www.memory-lovers.blog

クイズ詳細画面を Vue-routerからは /quizzes/show?id=xxxx/quizzes/:quiz-id の 2通りでアクセスできるようにしてやります。 /quizzes/:quiz-id のURLはSPAでは対応する静的ファイルは生成されないので、リロードするとページが見つからない状態になります。 この部分をcloud functionで拾ってやります。具体的には以下のような記述をします。

 "rewrites": [
      {
        "source": "/quizzes/*",
        "function": "quiz"
      }
  ]

これで クローラなどの /quizzes/:quiz-id への直アクセスはCloud Functionが起動し、 ここでmetaタグをよろしく出力し、 /quizzes/show?id=xxx ヘリダイレクトするという方法を取りました。

ハマったポイント

最初は /show?id=xxxx のページをCloud Functionで動かそうと思っていたのですが、 Firebase Hostingは 優先順位が以下のように決まっているので、既に静的コンテンツが存在する場合は、Cloud Functionは実行されずに、静的コンテンツがそのまま返ります。 そして SPAでgenerateした際は実際は /show/index.html が生成されているのですが、ここで静的コンテンツの名前が完全一致していることにきづけず、Cloud Functionを設定しているのに動かない!! となって時間を食ってしましました。

firebase.google.com

/__/* パスセグメントで始まる予約済みの名前空間

リダイレクトの構成

正確に一致する静的コンテンツ

リライトの構成

カスタムの 404 ページ

デフォルトの 404 ページ

また、Firebase HostingからCloud Functionの起動が、Cloud Functionがus-central1 リージョンじゃないと駄目らしく、 東京リージョンでデプロイしたCloud Functionが動かない!!みたいになりました。

課題

一応やっつけで動いたのですが、以下の課題があります。

  • リダイレクトされたURLをそのまま共有すると、そのURLはOGPがでない。
  • Cloud Functionがそこそこ遅い。(キャッシュなどで対策すると良い?)

ただ、はてなのリンクでも以下のようにイイ感じで表示されるようになりました。 quizhub.info

他の方法

以下の記事ではCloud FunctionでNuxtを動かして、そこでSSRをやるという方法を取っています。こうすれば、上記のリダイレクトによってURLが変わってしまう課題は解消しそうです。

medium.com

また、今回は試していませんが、Netlify には Prerendering という機能があるそうなので、OGP対応に閉じるぐらいの要件なら、こちらに移るという手もありかなと思います。

所感

サクっとできそうだったので、思ったより手間取ってしまったので、残しておきました。 あまりスマートなやり方ではないと思いますが、根本的に解消するには、Firebase Hostingで頑張らずに、Nuxt.js などのSSRの仕組みを使用できる環境に移すべきだと思いました。