目的
Github Pages でパーマリンク(整形された動的URL)を使えるようにする。Github Pages では .htaccess
などによるURLの rewrite
ができないので、同等の機能を javascript のみで実現する。
必要なもの
- javascript のみ
※ Jekyll は使わない。
仕組み
- パーマリンクによる無効なURLを一旦
404.html
で受ける(Github Pages のデフォルト仕様) -
404.html
に仕込んだ javascript で、クエリストリング付きの有効なURLに変換して目的のページpost.html
にリダイレクト - リダイレクトされた目的のページ
post.html
で、historyAPI のreplaceState
を使ってURLを最初にリクエストされたパーマリンクに変換
基本構成と各ファイルがやっていること
--
|-- index.html
|-- 404.html(無効なパーマリンクを有効なURLに変換してリダイレクト)
|-- post.html(リクエストされたURLをパーマリンクに再変換)
サンプル
実際に GitHub Pages でサンプルサイトを公開中。
パーマリンクでの遷移を実現するためにやっていることは
- 404.html
- post.html
内に記述した下記 javascript のみ。
/*
* (JS部分のみ抜粋)
* パーマリンクをクエリストリング付きのURLに変換してリダイレクト
*/
// リダイレクト先のファイル名
var redirect_file_name = 'post.html';
// リダイレクトで使用するパラメータキー
var parameter_key = 'post_id';
// パーマリンクの取得
var path_name = window.location.pathname;
// クエリストリング付きのURLに変換してリダイレクト
var match_condition = new RegExp(redirect_file_name.replace('.html', '') + '/[a-z0-9-_]+$');
if (permalink = path_name.match(match_condition))
{
location.href = path_name.replace(permalink, '') + redirect_file_name + '?' + parameter_key + '=' + permalink[0].replace(/post\//, '');
}
/*
* (JS部分のみ抜粋)
* クエリストリング付きのURLをパーマリンクに再変換
*/
// ファイル名
var file_name = 'post.html';
// パラメータキー
var parameter_key = 'post_id';
// URLを取得
var path_name = window.location.pathname;
var query_string = window.location.search;
var base_dir = path_name.split(file_name)[0];
// パーマリンクに再変換
var match_condition = new RegExp(parameter_key + '=[a-z0-9-_]+$');
if (parameter = query_string.match(match_condition))
{
parameter_value = parameter[0].split('=')[1];
history.replaceState(null, null, base_dir + file_name.replace('.html', '/') + parameter_value);
document.title = parameter_value + ' | Github Pages Rewrite';
}
詳しくはこちらのサンプルソースから。
問題点
- リダイレクトが実行されるので明らかな遷移感がある
-
replaceState
が走る前に一瞬変換前のURLが見える(ときもある)
mod_rewrite
などWEBサーバのリライト機能と完全に同等というわけではなく、結果として同じことができている、ということ。
その他
Github Pages は拡張子なしのURLを受け付けるので、canonical
でURLの正規化さえしておけば固定ページのリライトを意識する必要はなさそう。
/contact.html
/contact
さいごに
Jekyll
の redirect_from
のほうがスマートですが、ワイルドカードや正規表現を使ったリダイレクトルールが作れなかったので無理やりこの方法を試してみました。
もっといい方法があればどなたかご教授ください。
そもそも S3
や Firebase
などリライトが可能なサービス使えよ、っていう話ですが、やっぱり CI や Pipeline の設定なしでそのまま本番デプロイできる Github Pages は便利だな、と思うので。
Github さんには rewrite 機能を json で設定できるなどの追加サービスを期待したいです。
以上です。