はじめに
現在、個人開発のデプロイ作業を進めています。React と Rails API を使った SPA を構築しており、フロントエンド部分は AWS の S3 を利用して静的ファイルをホスティングしています。しかし、動的 URL の処理でつまずいたため、本記事を備忘録として執筆しました。同じ問題に直面した方の参考になれば幸いです。
エラー内容
AWS の S3 を使用して静的ファイルをホスティングし、index.html を返すように設定しました。しかし、ユーザーの操作によって動的 URL が発行された際に、404 (Not Found: サーバーエラー) が表示されてしまう。
結論
HashRouterを使用して、クライアントサイドでナビゲーションを行うようにする。
原因
原因は BrowserRouter を使用していたことにあります。BrowserRouter では、すべての URL がサーバーに送信されるため、S3 のように静的ファイルのみを提供するサーバーでは、該当するページが見つからず 404 (Not Found) が表示されてしまう。
解決方法
HashRouter を使用します。
HashRouter は、React Router のルーの一種で、URL のハッシュ (#) を使ってルーティングを管理する仕組みです。
違いは以下の通り。
ルーター | 仕組み | サーバー設定が必要か? |
---|---|---|
BrowserRouter |
window.history.pushState を利用 |
必要 |
HashRouter |
window.location.hash を利用 |
不要 |
例えば、以下のURLにアクセスした時の挙動を比較します。
URL | BrowserRouter の挙動 | HashRouter の挙動 |
---|---|---|
http://example.com/expense | S3 は expense/index.html を探す → 404 Not Found | #/expense の部分はサーバーに送られず、React が処理する → 正しく動作 |
http://example.com/#/expense | サーバーに /expense は送られない → React が #/expense を処理できる | React が #/expense を解釈して Expense コンポーネントを表示 |
HashRouterの特徴
ハッシュベースのルーティング
HashRouterはURLのハッシュ部分(#以降)を使用して現在のアプリケーション状態を決定します。これにより、サーバーへのリクエストを発生させずにクライアントサイドでナビゲーションを行うことができます
クライアントナビゲーション
URLのハッシュ部分の変更を監視し、それに応じてUIを更新することで、ページ全体のリロードを避けながら動的でレスポンシブな体験を提供。
サーバー設定不要
HashRouterはサーバーサイドで特別な設定が不要です。これは、特に共有ホスティング環境や静的サイトのデプロイメントにおいて便利。
使用方法
import { HashRouter, Route, Routes, Link } from 'react-router-dom';
const App = () => {
return (
<HashRouter>
<nav>
<ul>
<li><Link to="/home">Home</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</nav>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</HashRouter>
);
};
export default App;
上記のコードでは、 内にナビゲーションリンク ( コンポーネント) とルート定義 ( コンポーネント) を含めています。リンクをクリックすると、URL が変更され、それに応じて対応するコンポーネントがレンダリングされます。
さいごに
今回は、個人開発においてフロントエンドを S3 にホスティングし、CloudFront で SSL 化する手法を採用しました。選択した理由は以下のとおりです。
コストが安価 → S3 は従量課金制で、EC2 を利用するよりも圧倒的に低コスト。
サーバーレスで管理不要 → EC2 のように OS やインスタンス管理が不要で、運用負荷がほぼゼロ。
静的ファイル配信に最適 → React のような SPA には S3 + CloudFront の組み合わせが理想的。
自分の手で作り上げたプロダクトが世界中からアクセス可能になる瞬間まで、引き続きバックエンド、データベースサーバの構築の手法をキャッチアップしたいです。