静的コンテンツでパスパラメータを利用する方法【Nuxt×Firebase Hosting】


実現したいこと

この様にURLに直アクセスでパスパラメータを取得する画面を静的コンテンツ(nuxt generate)で実現します。

普通にNuxtをgenerateしてデプロイするだけだと、内部リンク(nuxt-link等)からのアクセスでは表示できるのですが、パスを指定した外部からのアクセスでは404 Not Foundになってしまいますのでこれに対処します。

モチベーション

SSR(Hosting+Functions)にすれば当然簡単に実現できますが、FirebaseのCloud FunctionsだとHostingとの連携はリージョンが「us-central1」しか利用できない*1のでレイテンシが気になりますし、あまり利用数がないとコールドスタートなので起動が遅かったりで、Hostingだけでなんとかできないか模索しました。
*1 https://firebase.google.com/docs/hosting/functions?hl=ja

静的コンテンツでパスパラメータを利用する方法

Firebase Hostingのrewrite構成を設定するだけで可能です。

firebase.json
{
  "hosting": {
    "public": "app/dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/test/*/*/",  //アクセスを想定するパス構造を定義し、ルートのindex.htmlにリライトします
        "destination": "/test/index.html"
      },
      {
        "source": "/test/*/", //こちらは/test/_id/を想定
        "destination": "/test/index.html"
      }
    ]
  }
}

上記に対応したpagesのディレクトリ構成は以下の通りです。

./pages
└── test
   └── _id
      └── _no
         └── index.vue
      └── index.vue
   └── index.vue

ページは以下の様にパスパラメータを利用する際の通常通りで問題有りません。

/pages/test/_id/_no/index.vue
<template>
  <div>
    <div>TEST NO INDEX</div>
    <div>$route.path:{{ $route.path }}</div>
    <div>$route.params:{{ $route.params }}</div>
  </div>
</template>

<script>
export default {}
</script>

これで静的コンテンツのみでパスパラメータを実現することができます。