私はこのようなスタックオーバーフローで多くの同様の質問を経験しました one 。それぞれがreactアプリのデプロイについて異なる視点を持っています。
しかし、この質問は、redux、react-router、およびreact-router-redux。シングルページアプリケーションをホストする適切な方法を理解するのに多くの時間がかかりました。ここですべてのステップを集約しています。
私はreact-reduxアプリをS3にデプロイする手順を含む以下の回答を書きました。
反応アプリをs3にデプロイするための video チュートリアルがあります。これは、s3にアプリ自体をデプロイするのは簡単ですが、reactアプリでいくつかの変更を行う必要があります。わかりにくいので、手順としてまとめています。ここに行きます:
バケットポリシーを追加して、誰もが反応アプリにアクセスできるようにします。 作成されたバケット-> プロパティ-> 権限をクリックします。その中でバケットポリシーの編集をクリックします。バケットポリシーの例を次に示します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow Public Access to All Objects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
}
]
}
ログが必要な場合は、別のバケットを作成し、プロパティのログセクションでバケット名を設定します。
index.html(アプリの開始点)とerror.html、およびすべてのパブリックアセット(ブラウザー化されたreactJSアプリとその他のCSS、JS、imgファイル)が必要です。フォルダ。
相対これらすべてのパブリックファイルへの参照がindex.htmlにあることを確認してください。
ここで、プロパティ-> 静的ウェブサイトホスティングに移動します。 ウェブサイトホスティングオプションを有効にします。 index.htmlおよびerror.htmlをそれぞれフィールドに追加します。保存すると、エンドポイントを受け取ります。
最後に、react-reduxアプリがデプロイされます。すべての反応ルートは正しく機能します。ただし、リロードすると、S3はその特定のルートにリダイレクトされます。そのようなルートはまだ定義されていないため、error.htmlをレンダリングします。
静的ウェブホスティングの下にいくつかのリダイレクトルールを追加する必要があります。したがって、404が発生すると、S3はindex.htmlにリダイレクトする必要がありますが、これは#のようなプレフィックスを追加することによってのみ実行できます。 。これで、error.htmlに移動する代わりに、任意の反応ルートを使用してページをリロードすると、同じURLがロードされますが、プレフィックスは#! 。 リダイレクトルールの編集をクリックし、次のコードを追加します。
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName> [YOUR_ENDPOINT] </HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
それに応じて、そのプレフィックスを削除し、ルートを元のルートにプッシュする必要があります。これがreactアプリで行う必要のある変更です。 main.jsファイルがあります。これはreactアプリの開始点です。browserHistoryにリスナーを次のように追加します。
browserHistory.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
history.replace(path);
}
});
上記のコードはプレフィックスを削除し、履歴を正しいルート(HTML 5ブラウザの履歴)にプッシュします。たとえば、次のようになりますhttp://s3.hosting/#!/eventはhttp://s3.hosting/event に変更されます。そうすることで、react-routerがルートを理解し、それに応じて変更できるようになります。これが私のmain.jsファイルです。
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, compose, applyMiddleware} from 'redux';
import {Provider} from 'react-redux'
import {Router, Route, IndexRoute, browserHistory, useRouterHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import createLogger from 'redux-logger';
import thunk from 'redux-thunk';
const logger = createLogger();
const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);
const store = createStoreWithMiddleware(reducers);
const history = syncHistoryWithStore(browserHistory, store);
browserHistory.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
history.replace(path);
}
});
したがって、ブラウザ化またはWebパックされたreactアプリ(app.jsファイル)をアップロードすると、必要な処理が実行されます。すべてのものを集めるのが難しいと思ったので、これらすべてをステップとして集約しました。
この投稿に出くわした人がいて、history.listen関数の無限ループのためにソリューションが機能しない場合。私にとっての解決策は、history.replace(path)呼び出しに小さなタイムアウトを追加することでした。したがって、次のようになります。
history.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
setTimeout(() => {
history.replace(path);
}, 100);
}
});