🐹

Cloudflare PagesにNuxt 2のSPAを上げるとリロード時に404になる

2022/11/13に公開約2,000字

困ってること

router.push等のページ内遷移であれば問題なく動くんですが、リロードすると404になります。
全部で起こるわけではなくて、/users/_id.vueみたいなDynamic Pagesを使っているページで起こります。

調べてもあまり出てこなかったので自分なりの解決方法を書いておきます。
Nuxt BridgeやNuxt 3でどうなるのかは知らないです。

なぜ404になるか

SSGがそういう仕様だから。

If you want Nuxt to generate routes with dynamic params, you need to set the generate.routes property to an array of dynamic routes.

例えばRESTっぽいユーザー管理ページがあるとします。

pages
├── users
│   ├── _id
│   │   ├── edit.vue
│   │   └── index.vue
│   ├── create.vue
│   └── index.vue
├── index.vue

出力はこうなります。

./dist
├── users
│   ├── create
│   │   └── index.html
│   └── index.html
├── favicon.ico
├── index.html

nuxt generateでは、pagesディレクトリの構造に沿ってHTMLを生成します。
ただ、ダイナミックなルートだとどんな値が来るの予測できないので生成のしようがないです。
なので生成されません。

Cloudflare Pagesの仕様

HTMLファイルが無かった場合、そのディレクトリからさかのぼって404.htmlを探して返してくれます。

https://developers.cloudflare.com/pages/platform/serving-pages/#not-found-behavior

Not Found behavior

You can define a custom page to be displayed when Pages cannot find a requested file by creating a 404.html file. Pages will then attempt to find the closest 404 page. If one is not found in the same directory as the route you are currently requesting, it will continue to look up the directory tree for a matching 404.html file, ending in /404.html. This means that you can define custom 404 paths for situations like /blog/404.html and /404.html, and Pages will automatically render the correct one depending on the situation.

どう解決したか

Cloudflare Pagesの仕様をうまく使います。
Nuxt 2ではSSGのデフォルトフォールバックファイルが200.htmlですが、それを404.htmlに変えてしまいます。
https://nuxtjs.org/docs/configuration-glossary/configuration-generate/#fallback

nuxt.config.jsに設定を足して404.htmlを生成するようにしてくれれば終わりです。

export default {
  // ...
  generate: {
    // For Cloudflare Pages
    fallback: '404.html',
  },

Discussion

ログインするとコメントできます