😸

nuxtのredirectまとめ

2020/10/22に公開

まとめ

nuxtはたまに、そこそう動くの?という動きをするため、
nuxtのライフサイクル(asyncData、fetch、plugins、middleware)で使える
redirectメソッド(Nuxt 2.14.5時点)のまとめです。

redirectの動作仕様

redirectの書き方

  fetch({ redirect }) {
    redirect([status,] path [, query])
  }

のような書き方で,
ユーザーをpathで示されたルートにリダイレクトさせることができます。

status: 型 Number デフォルト302 (SSRの時の、レスポンスのステータスコードを指定する引数)
path: 型 String or Object (リダイレクトさせるURLを指定する引数)
query: 型 Object (URLクエリパラメータ を指定する引数)

pathはいろいろな形で指定できます。

  1. スキーム, ホスト名, ドメイン名を含んだURL文字列
    ex) path = https://www.google.co.jp/webhp

  2. ドメイン無しの絶対パスや相対パスの文字列
    ex) path="/users", path="./users"

  3. vue routerのrouter.push({path: "/users"})で使われるようなLocationオブジェクト

  • ex) path={ path: "users/1"}, path={ name: 'user', params: { userId: '123' } }

Locationオブジェクトの詳細
https://router.vuejs.org/ja/guide/essentials/navigation.html#router-push-location-oncomplete-onabort

SSR, CSR と pathの引数の指定別のredirectの動作

nuxtはSever Side Rendering(SSR)とClient Side Rendering(CSR)で動作が微妙に変わったりするので、分けて考えます。

SSRの場合は、300系のステータスコードとLocationヘッダで、リダイレクトさせます。

CSRの場合は、
外部URLなら、汎用ページ遷移Javascript関数のwindow.location.replace()
内部URLなら、vue routerの関数のrouter.push()
よしなにページ遷移させます。

SSR CSR
1 フルURL HTTPレスポンスが引数statusのコードで返り、pathのURLへリダイレクト window.location.replace(path)でURLが置き換わる
2 絶対パス・相対パス HTTPレスポンスが引数statusのコードで返り、pathのURLへリダイレクト router.pushでpathのURLへ遷移
3 Locationオブジェクト HTTPレスポンスが引数statusのコードで返り、Locationオブジェクトの表すURLへリダイレクト router.pushでLocationオブジェクトの表すURLへ遷移

所感

redirectのpath引数でvue routerのLocationオブジェクトが取れること、内部URLの場合、router.pushも使ってくれるところが盲点でした。
今まで、redirectはrouter.pushを使ってくれない。なのでredirectを使ったら、必ずSSRになると勘違いしていたため、redirectあまり使いたくないと思っていたのですが、普通に使えそうです。

ページの初期のデータ読み込みとリダイレクトの処理は、
nuxtライフサイクルでもvueライフサイクルのどちらでも書けるので、
割と混沌になりやすいと個人的に思っていたのですが、
ここら辺の処理はnuxtライフサイクルのみで完結させるのが、
nuxtの想定しているやり方、そして割とすっきり書けるやり方なのかもしれません。

参考

公式のドキュメントだとbeta版のGUIDEがredirect周りを詳しく書いてます。
https://ja.nuxtjs.org/guides/internals-glossary/context#redirect

あとはひたすらnuxt公式のコードリーディングです。
https://github.com/nuxt/nuxt.js/

このファイル
app.context.redirect =あたりの記述から、
pathの指定として、1・2・3のようなパターンがあること、
app.context.next()でページ遷移処理らしきことやっていることが分かりました。

そしてこのファイル
const next = ssrContext ? ssrContext.next : location => app.router.push(location)あたりの記述から
app.context.next()は、SSRとCSRで違うページ遷移処理をしていること、
CSRはおそらくapp.router.push(location)でページ遷移処理をしていることが分かりました。

最後にこのファイル
const createNext =あたりの記述から
app.context.next()はSSRでは, 300系のステータスコードとLocationヘッダで、リダイレクト処理をしていそうなことが分かりました。

Discussion