Webサイトを構築するときにURL構造をどのように整えれば良いかは最も難しい問題の一つである。グーグルの検索エンジン最適化スターターガイドによると、トップページを基準として自然な階層構造を作ろう、URLの末端を削除した時に上位のディレクトリにきちんとアクセスできるようにしようなどと書かれている。例えば動物のサイトを作ることを考えると一階層目、即ちトップページが動物全般、そこから鳥類、哺乳類、爬虫類、両生類とカテゴリ分けをして第二階層を形成し、哺乳類からサル、犬、猫とカテゴリ分けして第三階層を形成する。URL構造としては下記のようになる。
こうするとカテゴリ分けされ秩序立っているために、どこにどのような記事があるかが理解しやすく、またURLがユーザの手によって削られたとしても上位概念のページが表示され分かりやすい。別のメリットもある。Googleの検索エンジンはschema.orgという構造化データの記述仕様をサポートしており、その仕様に従いパン屑リストを検索結果のスニペットに表示することができる。例えば猫で検索してcat.htmlが検索エンジンの検索結果画面に表示された場合には、TOP >> 哺乳類 >> 猫 とディレクトリ構造が表示され、サイトのどこにアクセスしているのかが一目でわかり、クリック率の上昇にも寄与する。(興味があれば https://developers.google.com/search/docs/data-types/breadcrumbs を参考に)。このパン屑リストも階層構造でサイトを作成しているからこそ成せる技である。
尚、ここでのファイルシステム上の各Pathは次のようになっている。
index.htmlはデフォルトドキュメントのため、animal.com/birds/index.htmlと指定しなくともアクセスする事ができる。(より具体的にはDirectoryIndex index.htmlとapacheに記述されている。) ただし、animal.com/birds/とanimal.com/birds/index.htmlは別URLとGoogleからは認識され、リンクポピュラリティが分散するため
RewriteRule ^/index.html$ / [R=301,L]
RewriteRule ^/(.*)/index.html$ /$1 [R=301,L]
などと記述してどちらかに統一しておくと良い。同様にwww.animal.comとanimal.comも別物とみなされるため、両方ともアクセスできるようにしている場合は片方をリダイレクトして揃える事が望ましい。
ここまでは良いのだが、このanimal.comには拡張性がない事に気付く。新しく哺乳類にクジラの記事を追加しようとwhale.htmlを追加する事は簡単にできるのだが、猫以下にシャム猫を追加しようとsiamese.htmlを作ろうとするとどうだろうか?今までのcat.htmlを/cat/に変えなければならないだろう。ところがcat.htmlが既に検索インデックスに登録されており、他からのリンクも張られているような状況だと折角の被リンクを失うために簡単には変更する事ができない。Apacheで301リダイレクトを設定してcat.htmlを/cat/へリダイレクトする事も可能であるが、毎回同じような状況になる度にApacheの設定をし直すのも効率が悪い。サイト拡張でこのような事態になるのならば最初から.htmlでアクセスさせるのはやめた方が良い。という事でmod_rewriteモジュールを用い、Apacheで次のように設定してみた。
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1.html [L]
説明をすると%{REQUEST_FILENAME}はapache.orgに説明があるようにファイルシステムのFull Pathを指す。%{DOCUMENT_ROOT}はVirtualHostを使用している時だけ必要になる。!-dはディレクトリが存在しない事を示す。この条件に当てはまる場合に/example/のURLでのアクセスを/example.htmlのファイルシステム上でのPathにマッピングする。
上記の例を使うと、animal.com/cat/でアクセスしてファイルシステム上に/cat/ディレクトリが存在しなければ、/cat.htmlを探すようになる。
最終的なApacheの設定は次のようになった。
RewriteEngine On
RewriteRule ^/index.html$ / [R=301,L]
RewriteRule ^/(.*)/index.html$ /$1 [R=301,L]
RewriteRule ^/(.*).html /$1/ [R=301,L]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1.html [L]
これにより拡張性が担保され、サイト拡大時にも適切な構造を保つ事ができる。