web-dev-qa-db-ja.com

手動で更新または書き込みを行ったときにReact-router URLが機能しない

私は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はサーバーに何も要求する必要はありません。

EDIT2: 私のルーター全体。

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);
});
438
DavidDev

受け入れられた回答に対するコメントとこの質問の一般的な性質(「動作しない」)を見て、ここに含まれる問題に関するいくつかの一般的な説明に適した場所であると思いました。したがって、この回答は、OPの特定のユースケースに関する背景情報/詳細として意図されています。どうか我慢してください。

サーバー側とクライアント側

これについて最初に理解しておくべき大きなことは、URLが解釈される場所が2つあるのに対し、「昔」には1つしかなかったことです。以前は、生活が単純だったときに、一部のユーザーがhttp://example.com/aboutのリクエストをサーバーに送信し、URLのパス部分を検査し、ユーザーがAboutページをリクエストしていると判断し、そのページを送り返しました。

React-Routerが提供するクライアント側ルーティングでは、物事はそれほど単純ではありません。最初は、クライアントにはJSコードがまだロードされていません。そのため、最初の要求は常にサーバーに対して行われます。その後、ReactやReact Routerなどをロードするために必要なスクリプトタグを含むページが返されます。これらのスクリプトがロードされた場合にのみ、フェーズ2が開始します。フェーズ2では、ユーザーが「About us」ナビゲーションリンクをクリックすると、URLが変更されますローカルのみからhttp://example.com/aboutHistory API)によって可能になります )、ただしサーバーへの要求は行われません。代わりに、React Routerはクライアント側で処理を行い、どのReactビューをレンダリングするかを決定してレンダリングします。 aboutページがREST呼び出しを行う必要がないと仮定すると、既に完了しています。サーバーリクエストが発生することなく、HomeからAbout Usに移行しました。

したがって、基本的にリンクをクリックすると、アドレスバーのURLを操作するJavascriptが実行されます[ページの更新を行わない。これにより、Reactルーターがページ遷移を実行します。 クライアント側

ただし、アドレスバーにURLをコピーして貼り付け、友人に電子メールで送信するとどうなるかを考えてみましょう。あなたの友人はあなたのウェブサイトをまだロードしていません。つまり、彼女はまだphase 1にいます。いいえReactルーターはまだマシン上で実行されていません。そのため、彼女のブラウザはhttp://example.com/aboutに対してサーバー要求を行います。

そして、ここからトラブルが始まります。今までは、サーバーのwebrootに静的なHTMLを配置するだけで済みました。しかし、それは他のすべてのURLに対して404エラーを与えますサーバーから要求されたとき。これらの同じURLは正常に機能しますクライアント側で、なぜならReactルーターがあなたのためにルーティングを行っていますが、失敗しますサーバー側でサーバーにそれらを理解させる。

サーバー側とクライアント側のルーティングの組み合わせ

http://example.com/about URLをサーバー側とクライアント側の両方で機能させる場合は、サーバー側とクライアント側の両方でそのルートを設定する必要があります。理にかなっていますか?

そして、ここから選択が始まります。解決策は、bootstrap HTMLを返すキャッチオールルートを介した問題のバイパスから、サーバーとクライアントの両方が同じJSコードを実行する完全同形アプローチにまで及びます。

問題を完全に回避する:ハッシュ履歴

ブラウザ履歴 ではなく ハッシュ履歴 を使用すると、aboutページのURLは次のようになります。http://example.com/#/aboutハッシュの後の部分(# )シンボルはサーバーに送信されません。したがって、サーバーはhttp://example.com/のみを認識し、期待どおりにインデックスページを送信します。 React-Routerは#/about部分を選択し、正しいページを表示します。

欠点

  • 「ugい」URL
  • このアプローチでは、サーバー側のレンダリングは不可能です。検索エンジン最適化(SEO)に関する限り、Webサイトはコンテンツがほとんどない単一のページで構成されています。

キャッチオール

このアプローチでは、ブラウザ履歴を使用しますが、/*index.htmlに送信するサーバー上でキャッチオールを設定するだけで、ハッシュ履歴とほぼ同じ状況を効果的に提供します。ただし、クリーンなURLがあり、ユーザーのお気に入りをすべて無効にすることなく、後でこのスキームを改善できます。

欠点

  • 設定がより複雑
  • まだ良いSEOではない

ハイブリッド

ハイブリッドアプローチでは、特定のルートに特定のスクリプトを追加することにより、キャッチオールシナリオを拡張します。簡単なPHPスクリプトを作成して、コンテンツを含むサイトの最も重要なページを返すことができるため、Googlebotは少なくともページの内容を確認できます。

欠点

  • さらに複雑な設定
  • あなたが特別な治療を与えるルートに対してのみ良いSEO
  • サーバーとクライアントでコンテンツをレンダリングするためのコードを複製する

同型

Node JSをサーバーとして使用して、両端で同じ JSコードを実行できるとしたらどうでしょうか。これで、すべてのルートが単一の反応ルーター構成で定義され、レンダリングコードを複製する必要がなくなりました。これはいわば「聖杯」です。サーバーは、クライアントでページの遷移が発生した場合に最終的に同じマークアップを送信します。このソリューションは、SEOの観点から最適です。

欠点

  • サーバーmust(実行可能)JSを実行します。 Java i.c.wを試しました。 Nashornが、それは私のために働いていません。実際には、ほとんどの場合、Node JSベースのサーバーを使用する必要があります。
  • 多くのトリッキーな環境問題(サーバー側などでwindowを使用)
  • 急な学習曲線

どちらを使うべきですか?

あなたが逃げることができるものを選択してください。個人的には、キャッチオールはセットアップするのに十分簡単であると思うので、それが私の最小になるでしょう。この設定により、時間の経過とともに改善することができます。サーバープラットフォームとして既にNode JSを使用している場合、同形アプリの実行を確実に調査します。はい、それは最初は難しいですが、一度それを理解したら、それは実際には問題に対する非常にエレガントな解決策です。

基本的に、私にとっては、それが決定的な要因になります。サーバーがNode JSで実行されている場合、同形になります。それ以外の場合は、キャッチオールソリューションに進み、時間の経過とSEO要件に応じて、それを拡張します(ハイブリッドソリューション)。

Reactによる同形(「ユニバーサル」とも呼ばれる)レンダリングの詳細については、このテーマに関するいくつかの優れたチュートリアルがあります。

また、開始するには、スターターキットをご覧になることをお勧めします。テクノロジースタックの選択に一致するものを1つ選択します(ReactはMVCの単なるVであり、完全なアプリを構築するにはさらに多くのものが必要です)。 Facebook自体が公開しているものを見てみましょう。

または、コミュニティの多くのいずれかを選択します。すべてのインデックスを作成しようとするニースのサイトがあります:

私はこれらから始めました:

現在、私は上記の2つのスターターキットに触発された自作のユニバーサルレンダリングバージョンを使用していますが、現在は古くなっています。

あなたの探求で頑張ってください!

845
Stijn de Witt

ここでの答えはすべて非常に役に立ちます。私にとって効果的だったのは、Webpackサーバーを経路を予想するように構成することでした。

  devServer: {
    historyApiFallback: true,
    contentBase: './',
    hot: true
  },

HistoryApiFallbackは、この問題を解決したものです。これでルーティングは正しく機能し、ページを更新したりURLを直接入力することができます。ノードサーバーの回避策について心配する必要はありません。この答えは明らかにwebpackを使用している場合にのみ有効です。

編集:これが必要である理由の詳細な理由については私の答えをここに見てください: https://stackoverflow.com/a/37622953/5217568

88
jmancherje

React Router V4 Usersの場合:

あなたが他の答えで言及されたハッシュ履歴技術によってこの問題を解決しようとするならば、それに注意してください

<Router history={hashHistory} >

v4では動作しません。代わりにHashRouterを使用してください。

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

参照: https://reacttraining.com/react-router/web/api/HashRouter

42
user2875289

あなたのhtaccessを変更してこれを挿入することができます:

RewriteBase /
RewriteRule ^index\.html$ - [L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

私はreact: "^15.3.2"react-router: "^3.0.0"history: "^4.3.0"を使っています、

40
BrahimS

ナビゲーションは、クライアント上で行われるのか、サーバー上で行われるのかに応じて、2つの異なる方法で呼び出すことができます。クライアント側の操作用に設定しました。重要なパラメータは、 runメソッド の2番目の場所です。

React Router Linkコンポーネントを使用すると、ブラウザのナビゲーションがブロックされ、transitionToが呼び出されてクライアントサイドのナビゲーションが行われます。 HistoryLocationを使用しているので、アドレスバーの新しいURLをシミュレートすることによってナビゲーションの錯覚を完成させるためにHTML5履歴APIを使用します。古いブラウザを使用している場合、これは機能しません。 HashLocationコンポーネントを使う必要があるでしょう。

Refreshを押すと、ReactコードとReact Routerコードをすべて回避します。サーバーは/joblistの要求を受け取り、それは何かを返さなければなりません。サーバーでは、正しいビューをレンダリングするために、要求されたパスをrunメソッドに渡す必要があります。同じルートマップを使用できますが、おそらくRouter.runへの別の呼び出しが必要になります。 Charlesが指摘したように、あなたはこれを処理するためにURL書き換えを使うことができます。もう1つの選択肢は、node.jsサーバーを使用してすべての要求を処理し、パスの値をlocation引数として渡すことです。

たとえば、エクスプレスでは、次のようになります。

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

要求パスがrunに渡されていることに注意してください。これを行うには、レンダリングされたHTMLを渡すことができるサーバーサイドビューエンジンが必要です。 renderToStringを使用したり、サーバー上でReactを実行する際には、他にもいくつか考慮事項があります。ページがサーバーにレンダリングされると、アプリケーションがクライアントにロードされると、再度レンダリングされ、必要に応じてサーバーサイドにレンダリングされたHTMLが更新されます。

26
Todd

Index.html headに、以下を追加します。

<base href="/">
<!-- This must come before the css and javascripts -->

それから、webpack dev serverで実行しているときは、このコマンドを使用してください。

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallbackは重要な部分です

18
Efe Ariaroo

Webpack Dev Serverにはこれを有効にするオプションがあります。 package.jsonを開き、--history-api-fallbackを追加します。この解決策は私のために働いた。

https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls#configuring-your-server

14
srijishks

AWS Static S3 Hosting&CloudFrontを介して反応型アプリをホストしている場合

この問題は、/ some/other /パスがS3フォルダに存在することを想定していたため、CloudFrontが403 Access Deniedメッセージで応答していましたが、そのパスはReactのreact-routerによるルーティングに内部的にのみ存在します。

解決策は、配布エラーページルールを設定することでした。 CloudFrontの設定に行き、あなたのディストリビューションを選択してください。次に「エラーページ」タブに行きます。 「Create Custom Error Response」をクリックして403のエントリを追加します。これがエラーステータスコードです。応答ページのパスを/index.htmlに、ステータスコードを200に設定します。その結果、その単純さに驚かされます。インデックスページは提供されますが、URLはブラウザに保存されるため、反応アプリケーションがロードされると、URLパスが検出され、目的のルートに移動します。

エラーページ403の規則

12
th3morg

これはあなたの問題を解決することができます

プロダクションモードのReactJSアプリケーションでも同じ問題に直面しました。これが問題の2つの解決策です。

1.ルーティング履歴を、代わりにbrowserHistoryの代わりに "hashHistory"に変更します。

 <Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
 </Router>

今コマンドを使用してアプリを構築します

Sudo npm run build

それから、buildフォルダをあなたのvar/www /フォルダに置いてください。これでアプリケーションはそれぞれのURLに#タグを追加してうまく動作しています。好き

localhost /#/ home localhost /#/ aboutus

解決策2:browserHistoryを使用して#タグを付けずに

あなたのルーターであなたのhistory = {browserHistory}を設定してください、今Sudo npm run buildを使ってそれを構築してください。

404見つからないページを解決するには、 "conf"ファイルを作成する必要があります。confファイルは次のようになります。

以下のコマンドを入力して端末を開きます。

cd/etc/Apache2/sites-available ls nano sample.conf次の内容を追加してください。

 <VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${Apache_LOG_DIR}/error.log
    CustomLog ${Apache_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

次のコマンドを使用してsample.confファイルを有効にする必要があります。

cd /etc/Apache2/sites-available
Sudo a2ensite sample.conf

それから、SudoサービスApache2 reloadまたはrestartを使用して、Apacheサーバーをリロードするように求められます。

次にlocalhost/buildフォルダを開き、以下の内容の.htaccessファイルを追加します。

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

これでアプリは正常に動作しています。

注:0.0.0.0 ipをローカルIPアドレスに変更します。

これについて疑問がある場合は、コメントをお願いします。

私はそれが他の人に役立つことを願っています。

12
Venkatesh Somu

私はちょうど今ウェブサイトを作成するためにcreate-react-appを使用し、ここに提示された同じ問題を抱えていました。 react-router-domパッケージのBrowserRoutingを使います。私はNginxサーバー上で実行していて、それを解決したのは/etc/nginx/yourconfig.confに以下を追加することでした

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

Appacheを実行している場合、これは.htaccessに以下を追加することに対応します

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

これもFacebook自身が提案した解決策のようであり、見つけることができます ここ

11
Aidin

プロダクションスタック:React、React Router v4、BrowswerRouter、Express、Nginx

1)可愛いURL用のUser BrowserRouter

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2)/*を使用して、すべての未知の要求にindex.htmlを追加します。

// server.js

app.get('/*', function(req, res) {   
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

3)webpack -pを含むwebpackをバンドルする

4)nodemon server.jsまたはnode server.jsを実行する

編集:あなたはnginxにサーバブロックでこれを処理させて、ステップ2を無視させることを望むかもしれません:

location / {
    try_files $uri /index.html;
}
8
Isaac Pak

これをwebpack.config.jsに追加してください。

devServer: {
      historyApiFallback: true
  }
8
suraj

以下のコードでパブリックフォルダ内に ".htaccess"ファイルを追加してみてください。

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  
6
Kiran Joshi

Create React Appを使用している場合:

この問題については、Create React Appページで _ here _ を参照してください。たとえば、フロントエンドコードにはReact Router v4とNetlifyを使用します。必要なのは、私のパブリックフォルダ( "_redirects")に1つのファイルを追加し、そのファイルに1行のコードを追加することだけでした。

/*  /index.html  200

今すぐ私のウェブサイトは正しくブラウザに入力したときや誰かがリフレッシュを押したときにmysite.com/pricingのようなパスをレンダリングします。

4
Colton Hicks

このトピックは少し古く、解決されていますが、私はあなたに単純明快でより良い解決策を提案したいと思います。 Webサーバーを使用している場合は機能します。

各Webサーバーには、http 404の場合にユーザーをエラーページにリダイレクトする機能があります。この問題を解決するには、ユーザーをインデックスページにリダイレクトする必要があります。

Javaベースサーバー(Tomcatまたは任意のJavaアプリケーションサーバー)を使用している場合、解決策は次のようになります。

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

例:

  • GET http://example.com/about
  • このページはサーバー側に存在しないため、Webサーバーはhttp 404をスローします
  • エラーページ設定は、index.jspページをユーザに返すようにサーバに伝えます。
  • クライアント側のURLはまだ http://example.com/about なので、JSはクライアント側で残りの仕事をします。

それはそれです、もう魔法の必要はありません:)

3
zappee

Index.htmlにフォールバックする場合は、index.htmlファイルに次のように記述してください。

<script>
  System.config({ baseURL: '/' });
</script>

これはプロジェクトによって異なります。

2
Matt Goo

IIS上でReactアプリケーションをホストしている場合は、次のものを含むweb.configファイルを追加するだけです。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

これはIIS serverに404エラーの代わりにメインページをクライアントに返すように指示し、ハッシュ履歴を使う必要はありません。

2
Chtiwi Malek

Firebaseを使用している場合は、アプリのルート(ホスティングセクション)にあるfirebase.jsonファイルにrewritesプロパティがあることを確認するだけです。

例えば:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

これが他の誰かにフラストレーションの溜まりと時間の無駄を省くことを願っています。

ハッピーコーディング...

件名についてさらに読む:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI: "シングルページアプリとして設定する(すべてのURLを/index.htmlに書き換え)" /

2
Joshua Dyck

私はまだサーバーサイドレンダリングを使っていませんが、Linkはほとんどの場合うまく機能しているように見えますが、パラメータがあると失敗するというOPと同じ問題に遭遇しました。私は自分の解決策をここで文書化して、誰かに役立つかどうかを確認します。

私のメインのjsxはこれを含みます:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

これは最初にマッチしたリンクではうまくいきますが、そのモデルの詳細ページにネストされた<Link>式の中で:idが変わったとき、URLはブラウザバーで変わりますがページのコンテンツはリンクモデルを反映するように変わりません。

問題は、モデルをcomponentDidMountに設定するためにprops.params.idを使用していたことです。コンポーネントは一度だけマウントされるため、最初のモデルはページに固定され、それ以降のリンクは小道具を変更しますが、ページは変更されずにそのまま残ります。

componentDidMountcomponentWillReceiveProps(次の小道具に基づいています)の両方でモデルをコンポーネント状態に設定すると、問題が解決し、ページの内容が目的のモデルを反映するように変更されます。

2
Paul Whipp

.Net Core MVCを使用しているので、このようなことが役に立ちました。

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var url = Request.Path + Request.QueryString;
            return App(url);
        }

        [Route("App")]
        public IActionResult App(string url)
        {
            return View("/wwwroot/app/build/index.html");
        }
   }

基本的にMVC側では、Home/Indexで指定されているように、一致しないすべての経路はstartup.csに分類されます。 Indexの中で、元のリクエストのURLを取得し、必要な場所に渡すことができます。

startup.cs

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
1
Elnoor

IISでホスティングしている場合私のwebconfigにこれを追加することは私の問題を解決しました

    <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
        <remove statusCode="500" subStatusCode="100" />
        <remove statusCode="500" subStatusCode="-1" />
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
        <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
        <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
    </httpErrors>

他のサーバーでも同様の設定ができます

1
Barny

万が一の場合、誰でもLaravelを使ったReact JS SPAの解決策を探しています。 受け入れられた答えは、そのような問題が起こる理由の最も良い説明です。すでに説明したように、クライアント側とサーバー側の両方を構成する必要があります。あなたのブレードテンプレートにjsバンドルファイルを含めて、URL facadeを必ずこのように使用してください。

<script src="{{ URL::to('js/user/spa.js') }}"></script>

ルートで、ブレードテンプレートがあるメインエンドポイントにこれを追加してください。例えば、

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

上記がブレードテンプレートの主要エンドポイントです。今度はオプションのルートも追加します。

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

発生する問題は、最初にブレードテンプレートがロードされ、次に反応ルータがロードされることです。そのため、'/setting-alerts'をロードすると、htmlとjsがロードされます。しかし'/setting-alerts/about'をロードすると、最初にサーバー側でロードされます。サーバー側では、この場所には何もないので、見つかりません。あなたがそのオプションのルータを持っているとき、それはその同じページをロードし、反応ルータもロードされ、そして反応ローダはどのコンポーネントを表示するかを決定します。お役に立てれば。

1
Koushik Das

バックエンドでExpressや他のフレームワークを使用している場合は、以下のように同様の設定を追加してWebpackのパブリックパスをチェックアウトすることができます。

` expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
  });`
1
user2849063

私は反応ルータ(アパッチ)と私のSPAのための解決策を見つけました。 .htaccessを追加するだけです

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

ソース: https://Gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

1

Joshua Dyckの答えにもっと情報を追加してください

Firebaseを使用していて、ルートルートとサブディレクトリルートの両方を使用したい場合は、firebase.jsonに次のコードを追加する必要があります。

{
  "hosting": {
    "rewrites": [
      {
        "source": "*",
        "destination": "/index.html"
      },
      {
        "source": "/subdirectory/**",
        "destination": "/subdirectory/index.html"
      }
    ]
  }
}

例:

あなたはクライアントのためのウェブサイトを構築しています。 Webサイトの所有者は https://your.domain.com/management に情報を追加し、Webサイトのユーザーは https://your.domain.com に移動します。

この場合、あなたのfirebase.jsonファイルは以下のようになります。

{
  "hosting": {
    "rewrites": [
      {
        "source": "*",
        "destination": "/index.html"
      },
      {
        "source": "/management/**",
        "destination": "/management/index.html"
      }
    ]
  }
}
0
neomib

これは、サーバー上で何も変更する必要がないことを発見したフロントエンドの回避策です。

あなたのサイトがmysite.comであり、mysite.com/aboutへのReact Routeがあるとします。トップレベルコンポーネントをマウントするindex.jsでは、次のような別のルーターを配置できます。

ReactDOM.render(
<Router>
    <div>
        <Route exact path="/" component={Home} />
        <Route exact path="/about"
            render={(props) => <Home {...props} refreshRout={"/about"}/>}
        />
    </div>
</Router>,

仮想DOMの最上位コンポーネントの下のどこかに元のルーターがあると仮定しています。 Djangoを使用している場合は、.urlsでURLをキャッチする必要もあります。

urlpatterns = [
       path('about/', views.index),
]

ただし、これは使用しているバックエンドによって異なります。 mysite/aboutをリクエストすると、index.js(トップレベルコンポーネントをマウントする場所)に移動し、そこでコンポーネントのプロップではなく、ルートのレンダープロップを使用し、「/ about」をプロップとして渡すことができます。この例は、ホームコンポーネントです。

Home内で、componentDidMount()またはuseEffect()フックのいずれかで、以下を実行します。

useEffect() {   
   //check that this.props.refreshRoute actually exists before executing the 
   //following line    
   this.props.history.replace(this.props.refreshRoute);
}

ホームコンポーネントが次のようなものをレンダリングしていると仮定しました。

<Router>
   <Route exact path="/" component={SomeComponent} />
   <Route path="/about" component={AboutComponent} />
</Router>

Routes内のコンポーネントに小道具を渡す方法については、( React Routerによってレンダリングされたコンポーネントに小道具を渡す )に感謝します。

0
Stevie

例付きの完全なルーター (React Router v4):

サンプル作業例以下のプロジェクトをチェックしてください。

https://github.com/eh3rrera/react-router-4-example

ダウンロード後
1)プロジェクトをインストールするためのcmdの "npm install"
2。) "npm start"をクリックしてあなたの反応アプリを起動します。

注:あなたのウィンドウで実行するにはNode jsソフトウェアが必要です。 Mac OSにはノードデフォルトがあります。

乾杯

0
Muthu Kumar

IIS 10を使用している人にとって、これは正しいことをするためにあなたがすべきことです。これでb​​rowserHistoryを使用していることを確認してください。参考までに、ルーティングのコードを示しますが、これは重要ではありません。重要なのは、以下のコンポーネントコードの次のステップです。

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

問題はIISがクライアントのブラウザからリクエストを受け取ることであるため、URLをページを要求しているかのように解釈し、利用可能なページがないため404ページを返します。以下をせよ:

  1. IISを開く
  2. [サーバー]を展開し、次に[サイト]フォルダを開きます。
  3. Webサイト/アプリケーションをクリックしてください
  4. エラーページへ
  5. リストの404エラーステータス項目を開く
  6. 「静的ファイルの内容をエラー応答に挿入する」オプションの代わりに、「このサイトでURLを実行する」に変更し、「/」スラッシュ値をURLに追加します。

そしてそれは今うまくいくでしょう。

enter image description here enter image description here

助けになれば幸いです。 :-)

0

私はWebPackを使用しています、私は同じ問題を抱えていましたSolution =>あなたのserver.jsファイルに

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

https://github.com/ReactTraining/react-router/blob/master/FAQ.md#why-doesnt-my-application-render-after-refreshing

0
Vishal Singh

次のホームルート定義があると仮定します

<Route exact path="/" render={routeProps => (
   <Home routeProps={routeProps}/>
)}/>

{/*optional catch-all router */}
<Route render={routeProps => (
       <div><h4>404 not found</h4></div>
)}/>

ホームコンポーネントでは、ComponentWillMountイベントでリクエストをインターセプトできます。

const searchPath = this.props.routeProps.location.search;

if (searchPath){
    this.props.routeProps.history.Push("/" + searchPath.replace("?",""));
}
else{
    /*.... originally Home event */
}

これで、urlで/ joblistを呼び出す代わりに、/?joblistを要求できます。コンポーネントは、要求を/ joblistに自動リダイレクトします(パス内の余分な疑問符に注意してください)

0
user2674595

あなたがここに来て、Apacheを使用していて、.htaccessファイルを持っていない場合、これは私のために働いた設定ファイルです:

sites-enabled/somedomain.com.conf

<VirtualHost *:80>
    ServerName somedomain.com
    ServerAlias *.somedomain.com
    DocumentRoot /www/somedomain.com/build

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /www/somedomain.com/build/index.html [L,NC,QSA]

</VirtualHost>
0
DevB2F

私はこれと同じ問題を抱えていたそして これ 解決策は私達のために働いた..

バックグラウンド:

同じサーバー上で複数のアプリをホストしています。サーバーを更新すると、その特定のアプリのdistフォルダーのどこでインデックスを探すべきかがわかりません。上記のリンクは私達のために働いたものにあなたを連れて行くでしょう...私達が私達の必要性のための解決策を考え出すことにかなりの時間を費やしたのでこれが助けてくれることを願っています。

私たちは使っています:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

私のwebpack.config.js

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

私のindex.js

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

私のapp.js

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});
0
J. Parrish

更新時またはURLを直接呼び出す際の「GET/URLができない」エラーを修正しました。

与えられたリンクがこのようなルートになるように webpack.config.js を設定します。

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
    },
0
Lalit Tyagi

私はそれを扱うこの方法が好きです。この問題を解決するには、サーバー側で: yourSPAPageRoute/* を追加してください。

ネイティブHTML5 History APIでさえページ更新時の正しいリダイレクトをサポートしていないので(私の知る限りでは)このアプローチを採用しました。

注:選択された回答はすでにこれに対処していますが、私はより具体的になろうとしています。

急行ルート

Test - History API テスト済みで、これを共有したいだけでした。

それが役に立てば幸い。

0
Rehan

Preact-routerを使用したPreactの解決策

更新と直接アクセスで動作します

Googleでこれを発見した人のために、これはpreact-router +のハッシュ履歴のデモです。

const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
    <div>
        <AddressBar />

        <Router history={createHashHistory()}>
            <div path="/">
                <p>
                    all paths in preact-router are still /normal/urls.
                    using hash history rewrites them to /#/hash/urls
                </p>
                Example: <a href="/page2">page 2</a>
            </div>
            <div path="/page2">
                <p>Page Two</p>
                <a href="/">back to home</a><br/>
            </div>
        </Router>
    </div>
);

https://jsfiddle.net/developit/gLyL6rbn/ /

0
keemor

あなたが手に入れたときその非常に単純なリフレッシュDOMコンポーネントの後に403エラーを取得することはできません。 Webパックの設定に 'historyApiFallback:true'という1行を追加するだけです。これで私の一日が節約できます。

0
praveenkumar s