Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Github Pagesに公開したNuxt.jsアプリがリロードで404になる問題に対応する

Github Pagesに公開したNuxt.jsアプリがリロードで404になる問題に対応する

Next.jsで作成したSPAアプリにおいて動的に変更されるパスに対応したページをリロードすると404 Not Foundになる問題への対応方法を記述する。

本現象の原因

Nuxt.jsでは静的ファイル生成時には動的ルーティングに対応したルーティングが無視され、動的ルーティング用ファイルが生成されないため、この現象が発生する。

静的ルーティング

/listというパスに対して、/list/index.htmlというファイルが生成される。

動的ルーティング

/list/10というパスに対して、/list/10/index.htmlというファイルは生成されない。

よく見かける解決策

ググって出てくる解決方法としては以下の二つが挙げられるがそれぞれ問題を抱えている。

index.htmlにリダイレクト

Nuxt.jsで作成したSPAアプリをSpring Bootにホストする場合にもよく見られる方法で、404の発生しうるパスまたは404発生時の処理でindex.htmlにリダイレクトする。

この方法では確かに404 Not Foundは発生しなくなるが、リロードで表示されるのは元々表示していたページとは異なるため、目的とするページに再度遷移しなければならない。

動的ルーティングを生成する

以下の公式ページに載っている方法。

API: generate プロパティ - Nuxt.js

動的ルーティングパターンが固定の場合

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のリダイレクトページを呼び出し、元々表示していたページにリダイレクトするというもの。

動作イメージ

  1. 404.htmlにて、自身のパスを元にリダイレクトページ呼び出しパラメータを作成し、リダイレクトページにパスを連携
  2. リダイレクトページでは、引き継いだパラメータを元にアプリのパスを生成し、リダイレクト実施

ソースイメージ

layaouts/blank.vue

<template>
  <nuxt />
</template>

pages/redirect.vue

<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>

static/404.html

/<repository-name>/部分は、Github Pages公開時にnuxt.config.jsに設定したrouter baseを指定する。未設定の場合は/でよい。

GitHub Pages へデプロイ - Nuxt.js

<html>
<head>
  <script>
    var pathName = window.location.pathname;
    var redirectPath = '/<repository-name>/redirect';
    location.href = redirectPath + '?p=' + encodeURI(pathName);
  </script>
</head>
</html>

参考URL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment