私は React-router を使用していますが、リンク ボタンをクリックしている間は正常に動作しますが、Web ページを更新すると、必要なものが読み込まれません。
たとえば、localhost/joblist
私はリンクをクリックしてここに来たので、ログインしていてすべて正常です。しかし、Web ページを更新すると、次のメッセージが表示されます。
Cannot GET /joblist
デフォルトでは、このようには動作しませんでした。 最初は URL を と にしてlocalhost/#/
、localhost/#/joblist
問題なく動作しました。 しかし、この種の URL は好きではないので、 を消去しようとして、次のように#
記述しました。
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
この問題は では発生せずlocalhost/
、常に必要なものが返されます。
このアプリはシングルページなので、/joblist
サーバーに何も問い合わせる必要はありません。
私のルーター全体。
var routes = (
<Route name="app" path="/" handler={App}>
<Route name="joblist" path="/joblist" handler={JobList}/>
<DefaultRoute handler={Dashboard}/>
<NotFoundRoute handler={NotFound}/>
</Route>
);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
ベストアンサー1
サーバー側とクライアント側
これについて理解すべき最初の大きなことは、URL が解釈される場所が 2 か所あるのに対し、昔は 1 か所しかなかったということです。昔、生活がシンプルだった頃は、あるユーザーがhttp://example.com/about
サーバーにリクエストを送信し、サーバーは URL のパス部分を検査して、ユーザーが About ページをリクエストしていると判断し、そのページを送り返していました。
React Routerが提供するクライアントサイドルーティングでは、状況はそれほど単純ではありません。最初は、クライアントにはまだJavaScriptコードがロードされていません。そのため、最初のリクエストは常にサーバーに送られます。その後、ReactやReact Routerなどをロードするために必要なスクリプトタグを含むページが返されます。これらのスクリプトがロードされた場合にのみ、フェーズ2が開始されます。フェーズ2では、たとえばユーザーが「About us」ナビゲーションリンクをクリックすると、URLはローカルでのみ変更されますhttp://example.com/about
(履歴API)ですが、サーバーへのリクエストは行われません。代わりに、React Routerがクライアント側で処理を行い、どのReactビューをレンダリングするかを決定し、レンダリングします。Aboutページでは何もする必要がないと仮定すると、休む呼び出しが行われた場合、すでに完了しています。サーバー要求が発行されることなく、ホームから会社情報に移動しました。
つまり、基本的にリンクをクリックすると、ページの更新を引き起こさずにアドレスバーの URL を操作する JavaScript が実行され、React Router がクライアント側でページ遷移を実行します。
しかし、アドレスバーに URL をコピーして貼り付け、友人に電子メールで送信するとどうなるか考えてみましょう。友人はまだあなたの Web サイトを読み込んでいません。言い換えると、彼女はまだフェーズ 1にいるということです。彼女のマシンではまだ React Router は実行されていません。そのため、彼女のブラウザは にサーバー要求を送信しますhttp://example.com/about
。
そして、ここから問題が始まります。これまでは、サーバーのウェブルートに静的 HTML を配置するだけで済みました。しかし、サーバーから要求された他のすべての URL に対して404エラーが発生します。これらの同じ URL は、React Router がルーティングを行っているため、クライアント側では正常に機能しますが、サーバー側ではサーバーに理解させない限り失敗します。
サーバー側とクライアント側のルーティングを組み合わせる
URL をサーバー側とクライアント側の両方で動作させたい場合はhttp://example.com/about
、サーバー側とクライアント側の両方でルートを設定する必要があります。理にかなっていますよね?
ここから選択が始まります。解決策は、ブートストラップ HTML を返すキャッチオール ルートを介して問題を完全に回避することから、サーバーとクライアントの両方が同じ JavaScript コードを実行する完全な同型アプローチまで多岐にわたります。
問題を完全に回避する: ハッシュ履歴
とハッシュ履歴、 の代わりにブラウザ履歴、about ページの URL は次のようになります。http://example.com/#/about
ハッシュ ( ) 記号の後の部分は#
サーバーに送信されません。そのため、サーバーはhttp://example.com/
期待どおりにインデックス ページのみを認識して送信します。React Router はその#/about
部分を取得して正しいページを表示します。
欠点:
- 「醜い」URL
- このアプローチではサーバーサイドレンダリングは不可能です。検索エンジン最適化(SEO) に関して言えば、あなたのウェブサイトはほとんどコンテンツのない単一のページで構成されています。
包括的な
/*
このアプローチでは、ブラウザ履歴を使用しますが、に送信するサーバー上に catch-all を設定するだけでindex.html
、実質的にハッシュ履歴の場合とほぼ同じ状況になります。ただし、クリーンな URL が得られるため、ユーザーのお気に入りをすべて無効にすることなく、後でこのスキームを改善できます。
欠点:
- セットアップがより複雑
- まだSEOは良くない
ハイブリッド
ハイブリッド アプローチでは、特定のルートに特定のスクリプトを追加することで、包括的なシナリオを拡張します。サイトの最も重要なページをコンテンツとともに返す簡単な PHP スクリプトをいくつか作成すれば、Googlebot は少なくともページの内容を確認できます。
欠点:
- セットアップがさらに複雑
- 特別な扱いをするルートにのみSEOが有効
- サーバーとクライアントでコンテンツをレンダリングするためのコードを複製する
同型
もしもNode.js両方のエンドで同じJavaScript コードを実行できるように、サーバーと同じものを設定するにはどうすればよいですか? これで、すべてのルートが単一の react-router 構成で定義され、レンダリング コードを複製する必要がなくなりました。 これは、いわば「聖杯」です。 サーバーは、ページ遷移がクライアントで発生した場合とまったく同じマークアップを送信します。 このソリューションは、SEO の観点から最適です。
欠点:
- サーバーはJavaScriptを実行できなければなりません。私はJavaと組み合わせて実験しました。ナシュホルンですが、私の環境ではうまくいきません。実際には、ほとんどの場合、Node.js ベースのサーバーを使用する必要があることを意味します。
- 多くのトリッキーな環境問題(
window
サーバー側での使用など) - 急な学習曲線
どれを使えばいいでしょうか?
問題なく実行できるものを選択してください。個人的には、catch-all はセットアップが簡単だと思うので、これが最低限の要件です。このセットアップにより、時間の経過とともに改善することができます。すでにサーバー プラットフォームとして Node.js を使用している場合は、isomorphic アプリの作成をぜひ検討してください。確かに最初は大変ですが、慣れてしまえば、実際には問題に対する非常にエレガントなソリューションになります。
つまり、私にとっては、基本的にそれが決定的な要因になります。サーバーが Node.js で実行されている場合は、同型ソリューションを選択します。そうでない場合は、包括的なソリューションを選択し、時間が経過して SEO 要件が要求されるようになったら、それを拡張します (ハイブリッド ソリューション)。
React を使用した同型レンダリング (「ユニバーサル」とも呼ばれる) について詳しく知りたい場合は、このテーマに関する優れたチュートリアルがいくつかあります。
また、始めるにあたっては、スターターキットをいくつか見ることをお勧めします。テクノロジースタックの選択に合ったものを選んでください(Reactは、MVCC の完全なアプリを構築するには、さらに多くのものが必要です。まずは Facebook 自身が公開しているものを見てみましょう。
または、コミュニティが作成した多数のものの中から 1 つを選択してください。現在、それらすべてをインデックス化しようとしている優れたサイトがあります。
私はこれらから始めました:
現在、私は上記の 2 つのスターター キットからヒントを得た、自作バージョンのユニバーサル レンダリングを使用していますが、これらはすでに古くなっています。
あなたの探求の成功を祈ります!