お知らせ・ブログ一覧へ戻る

URLの.htmlを消す正しい.htaccess設定|末尾スラッシュで壊れる罠つき


URLの.htmlを消す正しい.htaccess設定|末尾スラッシュで壊れる罠つき

URLの.htmlを消す正しい.htaccess設定|末尾スラッシュで壊れる罠つき

サイトのURLが https://example.com/price.html のように拡張子付きで出ている。これを https://example.com/price の形にしたい——制作会社に相談すると「.htaccessでできます」と言われる、あの設定です。

先に結論を書きます。この設定は、ページごとにルールを足していく方式ではなく、「サーバー上に実ファイルがあるときだけ拡張子なしURLで配信する」という汎用ルールを1本だけ置く方式にしてください。 そして拡張子なしURLは、末尾にスラッシュを付けない形(/price)に統一します。この2点を最初に決めておけば、あとはHTMLファイルを置くだけで自動的に拡張子なしURLになり、ページが増えても.htaccessを触る必要がなくなります。

弊社graciautoは名古屋でホームページとランディングページの制作・運用を行っています。この記事では、実際に本番サーバーで運用しているルールの形と、公開前に必ず通している検証手順を整理します。設定そのものは10行に満たない短いものですが、壊れ方だけは派手なので、順番を守ることが唯一のコツです。

なぜ拡張子を消すのか

技術的な必然性はありません。/price.html のままでもGoogleは正しく評価しますし、検索順位に直接の差は生まれません。それでも消す理由は次の2つです。

目的 内容
見た目と口頭での伝えやすさ 名刺・チラシ・電話口で伝えるとき「スラッシュ プライス」で済む。「ドット エイチティーエムエル」を読み上げずに済む
将来の作り替えに備える WordPressや静的サイトジェネレーターへ載せ替えたとき、URLの形が変わらない。中身の作り方を変えてもURLを維持できるので、リダイレクトの手間と評価の目減りが起きない

実務上は2つ目が本命です。ランディングページを何本も追加していくサイトでは、最初にURLの形を決めておかないと、後から全ページに301リダイレクトを敷く作業が発生します。 制作の初期段階に決めるべき項目だと考えてください。

実装は「実ファイルがあるときだけ」の汎用ルール1本

ページごとに RewriteRule ^price$ price.html のような行を足していく書き方は、行数が増えるほど事故が起きます。正しいのは次の形です。

# 拡張子なしURLの汎用ルール
RewriteEngine On

# 1) .html付きでアクセスされたら拡張子なしへ301
RewriteCond %{THE_REQUEST} \s/+([^\s?]+)\.html[\s?] [NC]
RewriteRule ^ /%1 [R=301,L]

# 2) 拡張子なしURLで、実ファイル .html があるときだけ内部配信
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^([^.]+)$ $1.html [L]

この形の要点は2つ目の -f 条件です。「そのスラッグに対応する実ファイルが本当に存在するときだけ」内部的に読み替えるため、存在しないURLは素通りして通常どおり404になります。 ここを条件なしで書くと、ドットを含まないURLがすべて「.htmlファイルへのリクエスト」に読み替えられます。WordPressの記事URLや他のプログラムが処理するはずだったURLまで巻き込まれ、本来表示できていたページが404になります。 存在確認を1行入れるだけで、この巻き込みは起きません。

そしてこのルールには、運用上の大きな利点があります。今後LPを追加するときは「◯◯.html をドキュメントルート直下に置く」だけで、自動的に拡張子なしURLになります。 .htaccessを再編集する必要がありません。実際に、学習塾向けに制作した資料ページを本番へ載せた際もこの形を採用し、以降の追加ページはファイルを置くだけで同じURL形式が適用される状態にしています。

WordPressと同居させるときの置き場所

既存のWordPressが動いているサーバーに静的なLPを追加するケースはよくあります。このとき、上記のルールはWordPressが自動生成する # BEGIN WordPress# END WordPress のブロックの外側、かつファイルの先頭に置いてください。

理由は2つあります。ひとつは、WordPress側のブロックは更新のたびに自動で書き換えられるため、その中に手書きのルールを入れると消えるからです。もうひとつは、WordPressのブロックが「実ファイルが無いリクエストは全部WordPressへ渡す」という包括的なルールで終わっているため、後ろに書いたルールに処理が届かないことがあるためです。

この編集で最も避けたい事故は、.htaccessを追記ではなく上書きしてしまうことです。 WordPressのブロックごと消すと、パーマリンクの解決ができなくなり全ページが404になります。編集前に必ず現物をダウンロードしてバックアップを取り、編集後は「BEGIN/ENDブロックとHTTPS転送の記述が残っているか」を目視で確認する。この2手順を省かないでください。

なお、nginxとApacheを組み合わせた構成のレンタルサーバーでは、ドキュメントルート直下に置いた.htmlファイルがWordPress側の処理に吸い込まれないかは、実際に置いてみるまで確定しません。 本番で試す前にバックアップを取っておくのは、このためでもあります。

末尾スラッシュを付けると、CSSと画像が全部404になる

拡張子なしURLで最も多い事故がこれです。/price は正しく開けるのに、/price/ でアクセスするとページの見た目だけが完全に崩れる。HTMLは200で返っているのに、CSSも画像もJavaScriptも読み込まれない状態です。

原因はリライトの設定ではなく、HTML内の相対パスの解決先が変わることにあります。

アクセスされたURL ブラウザが assets/style.css を探しに行く先 結果
/price /assets/style.css 200(正常)
/price/ /price/assets/style.css 404(全滅)

ブラウザは「最後のスラッシュまでが現在のディレクトリ」と解釈します。/price/ はディレクトリとみなされるため、相対パスの起点が1階層深くなり、そこには何も存在しないので参照ファイルが全滅します。

対策は次のどちらかです。

  1. 末尾スラッシュなしに統一する(推奨)。HTML内のcanonical・og:url・構造化データ・サイト内リンクをすべて /price の形へ揃える
  2. HTML内の参照をすべて絶対パス(/assets/style.css のように先頭スラッシュ付き)へ書き換える

制作済みのHTMLに手を入れる量が少ないのは1です。 2は確実ですが、参照箇所を1つでも取りこぼすと同じ症状が残ります。どちらを採るにせよ、「スラッシュあり」「スラッシュなし」の両方が200を返す状態のまま放置しないことが重要です。同じ内容が2つのURLで開ける状態は、検索エンジンから見れば重複コンテンツです。

サブディレクトリの.htaccessは、親のルールを無効化する

もうひとつ、事前に知らないと必ず時間を溶かすのがこの挙動です。

サブディレクトリに.htaccessが存在すると、そのディレクトリ配下では親(ドキュメントルート)のリライトルールが適用されません。 子のファイルが優先され、親のルールは無視されます。

実案件で起きうるのは、たとえば /wp/ のようなサブディレクトリでWordPressを動かしているサイトで、そこ宛のリダイレクトをドキュメントルートの.htaccessに書いたのに1本も効かない、という形です。ルールの書き方は正しいのに動かないため、正規表現を疑って何度も書き直すことになります。

判断基準はシンプルです。転送や書き換えの対象がサブディレクトリ配下なら、そのディレクトリの.htaccessに書く。 サイト移行の際にこの点を先に確認しておけば、リダイレクトの全数検証で「特定ディレクトリだけ全滅」という結果を見ずに済みます。

日本語スラッグを301の対象にするときの注意

日本語のURL(/料金/ など)を含むサイトを整理する場合、301のルールにパーセントエンコードされた文字列(%e6%96%99%e9%87%91 のような形)を書くとそのルールだけが機能せず404になります。

ディレクトリ単位の.htaccessに書いたリライトルールは、エンコードされる前のパスに対して照合されるため、エンコード済み文字列を書いても一致しません。日本語スラッグを対象にするときは、エンコードせずそのままの日本語で記述します。 英字のルールだけ通って日本語のルールだけ死ぬのが典型的な症状なので、その現れ方を知っておくと切り分けが早く済みます。

あわせて、機械的なパターンでリダイレクトを書く前に、そのパターンに一致する実在ページが無いかを必ず調べてください。 「この形式のURLは存在しないはず」という前提でルールを置くと、条件に合致した実在ページを巻き込んで転送してしまいます。ルールを書く前に、対象パターンで実際のページ一覧を検索して突き合わせる——この一手間が誤爆を防ぎます。

公開前に必ず通す検証

.htaccessの変更は、見た目に異常が出ないまま裏側だけ壊れることがある種類の作業です。ブラウザで1ページ開いて確認、では足りません。次の項目をコマンドで実測してください。

確認項目 期待する結果
新URL(/price 200
旧URL(/price.html 301 → 新URLへ1ホップで着地
存在しないURL(/does-not-exist-xxx 404(200ならルールが広すぎる)
ページ内の全参照ファイル CSS・画像・JS・フォントをすべて抽出して全件200
既存のWordPress・管理画面 200のまま無傷
末尾スラッシュ(/price/ 意図した挙動(301または404。200かつ表示崩れが最悪

とくに4行目を省かないでください。 相対パスの事故はHTML自体が200で返るため、ステータスコードをトップページだけで確認していると通過してしまいます。ページ内の参照URLをすべて抽出して一件ずつ確認すると、404だけでなく権限設定の誤りによる403も同時に拾えます。

301については「1ホップで着地するか」を必ず見てください。 リダイレクトを重ねると転送の連鎖ができ、評価の受け渡しが弱くなるうえ、後から経路を追いにくくなります。

そして作業前にバックアップを取ること。 .htaccessは数百バイトのテキストファイルなので、日付を入れたファイル名で手元に保存するだけで済みます。このコストの低さに対して、失われるものが大きすぎるのがこのファイルの特徴です。

まとめ:決めるのは最初の1回だけ

  • 汎用ルール1本方式にする。 ページごとに行を足さない。実ファイルの存在確認(-f)を必ず入れる
  • 末尾スラッシュなしに統一する。 相対パスのアセットは、スラッシュが1つ増えるだけで全滅する
  • WordPressのブロック外・先頭に追記する。 上書きは全ページ404を招く
  • サブディレクトリ配下のルールは、そのディレクトリの.htaccessに書く
  • 検証は複数URL・複数観点で実測する。 存在しないURLが404を返すことまで確認する

拡張子なしURLは、一度正しく設定してしまえば以降は運用の手間がゼロになる設定です。逆に、設定を後回しにしてページが増えるほど、移行時のリダイレクト作業だけが積み上がります。 サイトを新しく作るとき、あるいはLPを増やしていく予定があるときは、最初の1ページ目を公開する前に決めてしまうのが最も安く済みます。

ホームページやランディングページのURL設計、既存サイトの移行でお困りのことがあれば、graciautoまでお気軽にご相談ください。

関連記事

2026.08.28

注文通知メールに何を入れておくべきか|店側が受け取る通知の項目設計

2026.08.28

ロゴの背景が白く四角く出るときの確認手順|PNGなら透過されているとは限らない

2026.08.28

業務の自動化で何を聞けば外さないか|依頼の言葉どおりに作ると効果が出ない理由


お知らせ・ブログ一覧へ戻る