反応ルーターでページを更新すると 404 問題が発生する

亚连
リリース: 2018-06-14 15:51:34
オリジナル
2106 人が閲覧しました

この記事では、react-router のブラウザ履歴のページ更新に関する 404 問題の解決策を主に紹介します。これは、React を使用して新しいプロジェクトを開発するときに、非常に実用的です。ページを更新すると、2 番目または 3 番目のレベルに直接アクセスできます。ルーティング時にアクセスが失敗し、404 またはリソース読み込み例外が発生します。この記事では、この問題を分析し、解決策をまとめます。

背景

webpack-dev-server をローカル開発サーバーとして使用する場合、通常は webpack-dev-server コマンドを使用するだけで起動できますが、プロジェクトが次の 2 つの状況にある場合、ネストされます。ルーティングと非同期読み込みルーティング:

    単一ページのアプリケーションルーティングを構築するために、react-router などのルーティングライブラリを使用します
  1. html-webpack-plugin プラグインを使用して、< を動的に挿入します。 ;script> HTML ドキュメントにロードされた js タグ
  2. 現時点では、localhost:9090 にアクセスするときはページと js およびその他のファイルをロードできますが、2 番目または 3 番目のレベルにアクセスする必要がある場合は、 localhost:9090/posts/92 などのページをルーティングまたは更新すると、次の 2 つの状況が発生する可能性があります:

    ページの読み込みに失敗し、Cannot Get (404) が返されます
  1. サービスが応答します。しかし、webpack 処理によって出力された html ファイルが返されず、js リソースをロードできなくなります。2 番目の状況は図に示すとおりです。

それでは、通常のアクセスと各ページのルーティング?ブロガーはソースを追跡し、ドキュメントの構成を検索して問題を解決しました。この記事は、問題解決プロセス全体の概要です。

問題を分析する

問題を発見したら、この問題は一般的に次の 2 つの理由によって引き起こされていると判断します。

webpack -dev-server サービス設定;
  1. react-router
  2. フロントエンドルーティングは問題を特定しやすく、分析に便利であり、react-router の方が馴染みがあるため、最初にクエリを実行します。ルーティングライブラリのreact-routerの関連設定情報を見ると、browserHistoryを使用すると実際のURLが作成され、ルートにジャンプした後の初期/リクエストの処理には問題がないことが記載されていることがわかりました。ページを更新するか、URL に直接アクセスすると、正しく応答できないことがわかります。詳細については、リファレンス ドキュメントを確認してください。このドキュメントには、いくつかのサーバー構成ソリューションも提供されています。
Node

const express = require(&#39;express&#39;)
const path = require(&#39;path&#39;)
const port = process.env.PORT || 8080
const app = express()

// 通常用于加载静态资源
app.use(express.static(__dirname + &#39;/public&#39;))

// 在你应用 JavaScript 文件中包含了一个 script 标签
// 的 index.html 中处理任何一个 route
app.get(&#39;*&#39;, function (request, response){
 response.sendFile(path.resolve(__dirname, &#39;public&#39;, &#39;index.html&#39;))
})

app.listen(port)
console.log("server started on port " + port)
ログイン後にコピー
Node をサービスとして使用する場合すべてのリクエストをリッスンし、ターゲットの HTML ドキュメント (js リソースを参照する HTML) を返すには、ワイルドカード * を使用する必要があります。

Nginx

nginxサーバーを使用している場合は、try_filesディレクティブのみを使用する必要があります:

server {
 ...
 location / {
  try_files $uri /index.html
 }
}
ログイン後にコピー

Apache

Apacheサーバーを使用している場合は、プロジェクトルートに.htaccessファイルを作成する必要がありますファイルには次の内容が含まれています:

RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
ログイン後にコピー

以下はサーバーの構成です。残念ながら、webpack-dev-server の組み込みサービスを使用しただけです。問題は、ルーティング リクエストが返された HTML ドキュメントと一致しないことです。そのため、webpack-dev-server ドキュメントで解決策を探す必要があります。

webpack-dev-server

このブロガーは、問題を明確に理解するまでに、公式の webpack-dev-server ドキュメントについて文句を言わなければなりません。ここには 2 つの状況があります。 publicPath は変更されていません。つまり、デフォルトである webpack 設定ファイルに値が宣言されていません。

ドキュメントを表示するにはここをクリックしてください

    デフォルト
  1. デフォルトでは、output.publicPath 値は変更されません。webpack-dev-server のhistoryApiFallback 設定のみを設定する必要があります:
  2. devServer: {
     historyApiFallback: true
    }
    ログイン後にコピー
  3. HTML5 履歴 API を使用している場合は、おそらくインデックスを提供する必要があります。 404 応答の代わりに .html を使用します。これは、historyApiFallback: true を設定することで実行できます

    アプリケーションが HTML5 履歴 API を使用している場合、404 または問題のあるリクエストに応答するために、index.html を使用する必要がある場合があります。historyApiFallback: true を設定するだけです。

カスタム値

ただし、Webpack 設定で Output.publicPath を変更した場合は、リダイレクト先の URL を指定する必要があります。これは、historyApiFallback.index オプションを使用して行われます

出力を変更した場合。 Webpack 設定ファイルの publicPath 値を指定した場合は、リクエストのリダイレクトを宣言し、historyApiFallback.index 値を設定する必要があります。

// output.publicPath: &#39;/assets/&#39;
historyApiFallback: {
 index: &#39;/assets/&#39;
}
ログイン後にコピー

プロキシ

上記の方法を使用しても問題を完全には解決できないことがわかり、ルーティング リクエストの応答例外が常に発生するため、ブロガーはより良い解決策を探し続けました。

ドキュメントを表示するにはここをクリックしてください

プロキシは、関数からの戻りに基づいてオプションでバイパスできます。この関数は、HTTP リクエスト、応答、および指定されたプロキシ オプションを検査でき、プロキシを続行する代わりに false または提供される URL パスを返す必要があります。リクエスト

代理提供通过函数返回值响应请求方式,针对不同请求进行不同处理,函数参数接收HTTP请求和响应体,以及代理配置对象,这个函数必须返回false或URL路径,以表明如何继续处理请求,返回URL时,源请求将被代理到该URL路径请求。

proxy: {
 &#39;/&#39;: {
  target: &#39;https://api.example.com&#39;,
  secure: false,
  bypass: function(req, res, proxyOptions) {
   if (req.headers.accept.indexOf(&#39;html&#39;) !== -1) {
    console.log(&#39;Skipping proxy for browser request.&#39;);
    return &#39;/index.html&#39;;
   }
  }
 }
}
ログイン後にコピー

如上配置,可以监听https://api.example.com域下的/开头的请求(等效于所有请求),然后判断请求头中accept字段是否包含html,若包含,则代理请求至/index.html,随后将返回index.html文档至浏览器。

解决问题

综合以上方案,因为在webpack配置中修改了output.publicPath为/assets/,所以博主采用webpack-dev-server Proxy代理方式解决了问题:

const PUBLICPATH = &#39;/assets/&#39;
...
proxy: {
 &#39;/&#39;: {
  bypass: function (req, res, proxyOptions) {
   console.log(&#39;Skipping proxy for browser request.&#39;)
   return `${PUBLICPATH}/index.html`
  }
 }
}
ログイン後にコピー

监听所有前端路由,然后直接返回${PUBLICPATH}/index.html,PUBLICPATH就是设置的output.publicPath值。

另外,博主总是习惯性的声明,虽然不设置该属性也能满足预期访问效果:

historyApiFallback: true
ログイン後にコピー

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在JS中实现点击下拉菜单内容同步输入框

实现输入框与下拉框联动

使用parcel.js打包出错的问题

以上が反応ルーターでページを更新すると 404 問題が発生するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!