URLを引っ越ししたときにGoogle検索が404になってしまう対策。
ユーザー側への不利益のみならず、自身のSEOへも悪影響がある。
Gatsby.jsは基本的にフォルダ階層がそのままURLへと変換される。
つまりフォルダ名を変更したり、階層を増やしたりする場合URL転送が逐一必要になる。
私の場合BLOG記事が増えすぎて年ごとにフォルダ分けしたためURL転送が必要となった。
サーバーがNetlifyであること(別サーバーだと:slug
などのプレースホルダは使用不可)
gatsby-plugin-netlify
がインストール済みであること(Netlifyを使っていれば普通入ってるはず)
他にライブラリ等はいらないので基本的にはすごく簡単。
具体的な私の例を見て示す。
/blog/
配下にあった記事を/blog/2020/
の配下へ配置し転送する。
まずは転送元と転送先をgatsby-node.js
に書く。
exports.createPages = ({ actions, graphql }) => { //ここはもともとあるコード
const { createPage, createRedirect } = actions //ここはもともとあるコード
//これが転送用の関数
createRedirect({
fromPath: "/blog/:slug",
toPath: "/blog/2020/:slug",
isPermanent: true
});
...以下略
コード内にcreateRedirect
を記述してbuild
するだけで転送設定は完了する。
オプションはシンプルで
fromPath
: こちらのURLにアクセスしたときにtoPath
: このURLへ転送するisPermanent
は一時的なサイト移転(あとでもとに戻す予定)でなければtrue
。つまりURLは変更したまま戻すことはないですよという意味。
基本はtrue
でいいはず。SEOに関わってくると思われるが詳しくは別サイトにて。
なんと、以上で転送設定は終わっている。
build
してNetlify
にdeployして本番で確認する。
createRedirect
はgatsbyが用意している基本機能なので簡単なのだ。
これで/blog/なんとか
にアクセスすると /blog/2020/なんとか
に正しく「301」コードにて転送される(SEO的にもGoogle検索も問題ない)
注意点はdevサーバーでは転送が行われないこと。
あくまでcreateRedirect
は本番サーバーのサーバー側の転送プログラムを呼び出すものであり、開発環境では意味がない。
さて、ここからは細かく説明するので必要な人のみどうぞ。
試しに次のリンクで/blog/
直下でアクセスすると/blog/2020/
へとリダイレクトが確認できる
/blog/2020-11-20-【Gatsby_js】やたら簡単!Netlifyでリダイレクト!(URL転送)/
このコロン:
から始まるのはNetlify側で設定されている変数のようなもの。プレースホルダーと呼ばれている。
スラッグの意味を知らないブロガーはあまりいないと思うが要するにここは「記事ごとに別々のタイトルが入りますよ」という意味。
/blog/hoge
なら/blog/2020/hoge
/blog/fuga/
なら/blog/2020/fuga
に転送される。
このサイト以外では恐らく次のコードで転送を推奨しているが私の場合は動作しないので後ほど解説する。
createRedirect({
fromPath: "/blog/*",
toPath: "/blog/2020/:splat",
isPermanent: true
});
この場合は恐らく/blog/a/b/c/d/e/
のように深い階層もまるごと/blog/2020/
に転送するコードとなる。
/blog/2020/a/b/c/d/e/
に転送されるはずだ。
しかしながら私のケースではこれは404
が表示される。後ほど詳しく解説する
※このコロンのあとに続くプレースホルダの詳細は公式を参照。
Redirect options | Netlify Docs
まず*
とsplat
を理解する前にファイルがある場合と無い場合で転送の挙動が異なるので覚えておきたい。
例えば今回の例のような転送が設定されている状態で/blog/a
にアクセスしたとする。
/blog/
直下にa
というファイルが存在した場合、転送は行われずa
の内容が表示される。
a
が存在しなければ/blog/2020/a
に転送される。
更に/blog/2020/a
も存在しなければここでようやく404
になる。
バグ?としたのは公式に詳しい解説がないからそうさせていただいた。
私のバグは「*
」と「:splat
」で転送すると/blog/
直下にファイルが存在しないのに転送が行われず問答無用で404
が返される。
これはなぜなのだろうか。
どうやら記事のタイトル(スラッグ)がすべて2020-
から始まっているのが悪さをしているらしい。
つまり
/blog/2020/2020-月-日-タイトル
というところに転送してほしいのだが「*
」か「:splat
」のどちらかでバグがあり先頭の2020
とフォルダ名の2020
は纏められて
/blog/2020-月-日-タイトル
でURLが解決してしまうのである。
結果404
記事タイトルの開始文字がフォルダ名とかぶる可能性がある転送は:slug
を使ったほうが良いのではと結論づける。
偶然フォルダ名とタイトルの前方が一致してしまった場合転送が行われないので十分注意である。
ただ、別の解決作として/2020/
のフォルダを/posts2020/
のように絶対被らないフォルダ名にするという手もある。
直下だけでなく深い階層も追従して転送するのであればこのような方法を考えると良いと思う。
公式に詳しい解説がないのであくまで私の推論になってしまったのだが、簡単な反面よくわからない挙動を偶然を引いてしまった。
もしだれか同じような不具合で困っている場合助けになれたら幸いである。