30代からのプログラミング学び直し!

10年エンジニアやってるけどいまだになんもわからん

History: pushState()でページ遷移せずにURLを動的に変更する

やりたいこと

JavaScriptで非同期(ajax)でデータを取得している、あるWebページがありまして、ページング時にもURLは変わらない(ページ遷移しない)作りだったのですが。SEO的な観点で、ページングしたらページ番号をURLに付与したくなりました。いまさら非同期をやめてサーバサイドで処理をするのも嫌だったので、フロントだけでURLを動的に変更できないか調べたところ、いとも簡単にできたので備忘録です。

結論、History: pushState()を使う

History: pushState() メソッド - Web API | MDN

ページネーションの番号をクリックした後に呼ばれるコールバック関数内で、history.pushState()を呼ぶ。これだけ。

clickCallback(pageNum) {
      history.pushState(null, '', pageNum);    // URLを動的に変更
},

大事なのは第3引数のURLの部分ですが、相対パス絶対パスも指定できるようです。ドキュメントだけだといまいち分からなかったので試してみました。 https://example.com/aaa/bbb というパスに対して実行した場合

history.pushState(null, '', '1');    // https://example.com/aaa/1 に書き換わる
history.pushState(null, '', '/1');   // https://example.com/1 に書き換わる(ルート相対パス)

相対パスの場合、末尾のスラッシュがあるかないかでも挙動が変わるので注意。 https://example.com/aaa/bbb/ というパスに対して実行した場合

history.pushState(null, '', '1');    // https://example.com/aaa/bbb/1 に書き換わる

クエリパラメータにページ番号を追加する

あとはどのようにページ番号付きのURLを生成するかですが、 https://example.com/aaa/bbb?page=1 のようにクエリパラメータに追加することにしました。

clickCallback(pageNum) {
      let url = new URL(location.href);
      url.searchParams.set('page', pageNum);
      history.pushState(
        null,
        '',
        `${url.pathname}?${url.searchParams.toString()}`
      );
},

これであれば、https://example.com/aaa/bbb?c=cccのような、任意のクエリパラメータを持つURLであっても、 https://example.com/aaa/bbb?c=ccc&page=1 となって問題なくページ番号を付与することができます。

一見難しそうに見えましたがいとも簡単に実装できました!HTML5便利〜✨ ついでに言うとURLオブジェクトもなかなか便利ですね。

URL: URL() コンストラクター - Web API | MDN

参考にさせていただきました : ページ移動せずにアドレスバーのURLを変更する | GRAYCODE JavaScript