【Nuxt3】オプションから消えたtrailingSlashに手動で対応するぞ!

シェアする:

この記事をおすすめしたい人

  • Nuxt3でtrailingSlashしようとしている人
  • Nuxt2のtrailingSlashに帰ってきてほしい人
  • つまりオレ

Nuxt v3の調査、trailingSlash編です。

trailingSlashというのはv2の頃にnuxt.config.jsで設定できていた項目で、こんな↓風に設定すると、


export default {
  router: {
    trailingSlash: true,
  },
}

ルート?っていうんでしたっけ、各ページのパス末尾にスラッシュが付くようになります。


//trailingSlashあり
https://dev.ore-shika.com/post/

//trailingSlashなし
https://dev.ore-shika.com/post

「末尾スラッシュが必要か」というのは各自の判断によると思いますが、URLの正規化の問題で少なくともどちらかには統一しないといけません。 デフォルトだと「/post/」でも「/post」でもアクセスできてしまいます。

今回はtrailingSlashありにするのが目的ですが、正規化の点でも大事な問題だと思います。

たぶんね、たぶん。

trailingSlashを考慮しないといけない場所

自前でtrailingSlashするとなると、たぶんこの↓3箇所?

  1. aタグやNuxtLinkのリンク先URL
  2. 旧$route.path
  3. スラッシュなしURLへアクセスがあった際のリダイレクト

モジュールで解決できないか?

@nuxtjs/seoというモジュールが対応しているようです。

ところがですね、実際にNuxtLinkでスラッシュなしURLを指定するとtrailingSlashになっておらず、そのためにSiteLinkというコンポーネントがあるようですが、toにパス指定しただけでエラー…。

そもそもリダイレクトもしてないっぽいし、今回は見送りに。 モジュール自体に興味があって、モジュールが何をやっているのか細かく調べる記事を書いてたのに、うちの環境だとエラー多すぎて諦めました。

他に対応モジュールあるのかな? あるなら正直そっちに任せたい。

NuxtLinkのリンク先URLへ対応

nuxt.config.tsで対応可能みたいです。


export default defineNuxtConfig({
  experimental: {
    defaults: {
      nuxtLink: {
        trailingSlash: 'append',
      }
    }
  }
})

これでtoにスラッシュなしを指定してもスラッシュありになります。 逆にスラッシュなしで統一したい場合は「append」の部分を「remove」にすればいいみたい。

ただこれ、「experimental」って実験的な項目なんじゃなかろうか。 今後もチェックしてメンテしないといけなさそうだけど、とりあえずヨシ。

リンクになるのはもうひとつAタグがありますが、コイツは無理よね? trailingSlashを考えなきゃいけないのは内部リンクで、内部リンクにAタグは使わないと思うので、Aタグを使わないことで回避しよう。

route.pathへの対応

現在のページのパスが入っているroute.pathですが、v3だとこんな↓感じに書きます。


const route = useRoute()

console.log(route.path)

これはどうも単純に今アクセスしているURLのパスを返してるだけっぽい。

なので次のリダイレクトの方が解決すれば自動で解決します。

スラッシュなしアクセスへの対応

「/post」みたいなパスでアクセスされた時に「/post/」にリダイレクトさせる処理です。

v3でのリダイレクトはnavigateToという関数を使うみたい。

ページ内での処理

ページコンポーネントのscript部分でリダイレクトが可能なようです。

処理としては、特定のページへアクセスがあった際にリダイレクトではなく、全てのページでスラッシュなしアクセスがあった場合にスラッシュ付きへリダイレクト、です。

なのでapp.vueにこの↓ようなコードを追加しました。


<script setup lang="ts">

const route = useRoute()

if ( !route.path.endsWith('/') ) {
  await navigateTo(route.path + '/')
}

</script>

うまくいきました。

app.vueがない場合はレイアウトの方でもよさそう。 それもないなら次のミドルウェアへ。

ミドルウェアで処理

意味を分かってないんですが、ミドルウェアというカテゴリがあってですね。 プロジェクトルートにmiddlewareというフォルダを作れば自動インポートされます。

グローバルで使う場合は末尾に「.global」つけろとあるので、ファイル名を「trailingSlash.global.ts」とかにして、先ほどと同じようなコードを書きました。


export default defineNuxtRouteMiddleware((to, from) => {
  if ( !to.path.endsWith('/') ) {
    return navigateTo(to.path + '/')
  }
})

これでもうまくいきました。

他モジュールでの動作

導入したモジュールにもパスを吐き出すものがあるので、それらのチェックと対策をしていきます。

@nuxtjs/sitemap

サイトマップを自動で出力してくれる@nuxtjs/sitemapです。

上のNuxtLinkとリダイレクトの問題をクリアした状態でサイトマップを出力すると、末尾スラッシュなし状態で出力されました。

インストールガイドにあるようにnuxt.config.tsにtrailingSlashの設定を追記↓すると、


export default defineNuxtConfig({
  site: {
    trailingSlash: true
  },
})

無事にサイトマップ内もスラッシュ付きになりました。

@nuxtjs/i18n

多言語化してくれる@nuxtjs/i18nです。

パスを出力する部分で僕が使ってるのはlocalePath(現在の言語の指定したパスを取得)、switchLocalePath(現在のページの指定した言語のパスを取得)くらいで、どちらもがスラッシュなしで出力しました。 localePathの方はスラッシュ付きの引数を渡してもスラッシュがなくなる頑固っぷり。

じゃーモジュールのオプションでと思って公式のオプション一覧を「slash」で検索してもそれっぽいものを見つからず。

まぁ上の関数の結果をチェックしてスラッシュ付ける関数を自分で作れば良いだけなので、@nuxtjs/sitemapがtrailingSlashオプションをどうやって参照しているんだろうとソースを眺めていたら、

i18nのソースに「trailingSlash」の文字が!

オプションで設定できるっぽい…。

nuxt.config.tsで指定できるようだったのでこの↓ように設定。


export default defineNuxtConfig({
  i18n: {
    trailingSlash: true,
  },
})

無事にスラッシュ付きになりました。

@nuxtjs/sitemap+@nuxtjs/i18n

@nuxtjs/sitemapと@nuxtjs/i18nの両方のモジュールが入っていると、言語ごとのサイトマップが出力されます。

trailingSlashの値をいろいろ変更して挙動をチェックすると、サイトマップ側だけtrueならスラッシュありのサイトマップに。 i18n側だけtrueならスラッシュなしのサイトマップに。

サイトマップにスラッシュをつけたいならサイトマップモジュール側をtrueにしないとダメっぽい。 つまり両方trueですね。

まとめ

Nuxt3で手動でtrailingSlashにする方法を考えてみました。

まだNuxt3は実働させられていないので、実働して問題が出たらそれを追加します。 他にもパス出力するモジュールあるかもだし。

以上、WordPressからお届けしました!

シェアする: