Next.jsで作成したSPAアプリにおいて動的に変更されるパスに対応したページをリロードすると404 Not Foundになる問題への対応方法を記述する。
Nuxt.jsでは静的ファイル生成時には動的ルーティングに対応したルーティングが無視され、動的ルーティング用ファイルが生成されないため、この現象が発生する。
/list
というパスに対して、/list/index.html
というファイルが生成される。
/list/10
というパスに対して、/list/10/index.html
というファイルは生成されない。
ググって出てくる解決方法としては以下の二つが挙げられるがそれぞれ問題を抱えている。
Nuxt.jsで作成したSPAアプリをSpring Bootにホストする場合にもよく見られる方法で、404の発生しうるパスまたは404発生時の処理でindex.htmlにリダイレクトする。
この方法では確かに404 Not Foundは発生しなくなるが、リロードで表示されるのは元々表示していたページとは異なるため、目的とするページに再度遷移しなければならない。
以下の公式ページに載っている方法。
nuxt.config.js
にルーティング指定を追加する。
export default {
generate: {
routes: [
'/users/1',
'/users/2',
'/users/3'
]
}
}
こちらはWebサイトを生成する場合に利用されると思われるが、APIやデータベースのデータによりルーティングが動的に変わるWebアプリケーションでは利用しづらい。
nuxt.config.js
にAPI等を先読みして動的ルーティングを都度生成する記述を追加する。
import axios from 'axios'
export default {
generate: {
routes: function () {
return axios.get('https://my-api/users')
.then((res) => {
return res.data.map((user) => {
return {
route: '/users/' + user.id,
payload: user
}
})
})
}
}
}
動的なルーティング変更に対応可能だが、全件検索となるため重いAPIでは検索負荷が掛かったり、複数のAPIがある場合はそれらを全て呼ぶ必要があることから、複雑なアプリでは利用が難しいと思われる。
Github Pagesでは自作の404.html
を利用可能であるため、これを利用してNuxt.jsアプリにリダイレクトさせた。
仕組みとしては、404.html
からNuxt.jsのリダイレクトページを呼び出し、元々表示していたページにリダイレクトするというもの。
404.html
にて、自身のパスを元にリダイレクトページ呼び出しパラメータを作成し、リダイレクトページにパスを連携- リダイレクトページでは、引き継いだパラメータを元にアプリのパスを生成し、リダイレクト実施
<template>
<nuxt />
</template>
<template>
<div></div>
</template>
<script>
export default {
layout: 'blank',
fetch({base, redirect, query}) {
const param = query.p
if (param === undefined) {
return redirect('/')
}
const redirectPath = '/' + param.replace(base, '')
return redirect(redirectPath)
}
}
</script>
/<repository-name>/
部分は、Github Pages公開時にnuxt.config.js
に設定したrouter base
を指定する。未設定の場合は/
でよい。
<html>
<head>
<script>
var pathName = window.location.pathname;
var redirectPath = '/<repository-name>/redirect';
location.href = redirectPath + '?p=' + encodeURI(pathName);
</script>
</head>
</html>