ホームページ  >  記事  >  ウェブフロントエンド  >  反応ルーターのブラウザ履歴更新ページ 404 問題を解決する方法

反応ルーターのブラウザ履歴更新ページ 404 問題を解決する方法

小云云
小云云オリジナル
2017-12-29 16:18:343404ブラウズ

React を使用して新しいプロジェクトを開発する場合、ページを更新して二次または三次ルーティングに直接アクセスすると、アクセスが失敗し、404 またはリソース読み込み例外が発生します。この記事では、この問題を分析し、解決策をまとめます。この記事では、react-router のブラウザ履歴更新ページの 404 問題の解決策を主に紹介します。困っている人はぜひ参考にしてください。

背景

webpack-dev-server をローカル開発サーバーとして使用する場合、通常の状況では、単に webpack-dev-server コマンドを使用するだけで起動できます。ただし、プロジェクトが次の 2 つの状況では、多くの場合、組み込みの Set ルーティングと非同期ロード ルーティングが必要になります。

  1. シングルページ アプリケーションのルーティングを構築するには、react-router などのルーティング ライブラリを使用します

  2. を使用します。 -plugin ロードされた js の 3f1c4e4b6b16bbbd69b2ee476dc4f83a タグを HTML ドキュメントに動的に挿入するプラグイン ;

この時点では、localhost:9090 にアクセスするとページと js およびその他のファイルが正常にロードされますが、第 2 レベルまたは第 3 レベルのルーティングにアクセスするか、localhost:9090/posts/92 などのページを更新する必要がある場合があります。次の 2 つの状況が考えられます:

  1. ページの読み込みに失敗し、ページを取得できない(404) が返されます。

  2. サービスは応答しますが、Webpack 処理によって出力された HTML ファイルが返されないため、js リソースを読み込めなくなります。 2 番目の状況は、図に示すとおりです。

  3. それでは、通常のアクセスを保証するために、各ページのルーティングをどのように処理すればよいでしょうか?ブロガーはソースを追跡し、ドキュメントの構成を検索して問題を解決しました。この記事は、問題解決プロセス全体の概要です。

問題を分析する


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

react-router road フロントエンド構成。 ;

  1. webpack-dev-server サービス構成

  2. react-router

フロントエンドルーティングは問題を特定しやすく、分析に便利であり、react-router に慣れているためです。まず、react-router ルーティング ライブラリにクエリを実行します。 関連する設定情報については、browserHistory を使用すると実際の URL が作成され、ルートにジャンプした後の初期/リクエストの処理には問題がないことがドキュメントに記載されていることがわかりました。ページを更新したり、URL に直接アクセスしたりすると、正しく応答できないことがわかります。詳細については、リファレンス ドキュメントを参照してください。このドキュメントには、いくつかのサーバー構成ソリューションも記載されています。サービスとして、ワイルドカード * を使用してすべてのリクエストをリッスンし、ターゲットの HTML ドキュメント (リソースの js html を引用) を返す必要があります。

Nginx


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


const express = require('express')
const path = require('path')
const port = process.env.PORT || 8080
const app = express()

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

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

app.listen(port)
console.log("server started on port " + port)


Apache

Apache サーバーを使用している場合は、 。 ht でプロジェクトのルート ディレクトリにアクセスします。 ファイルには次の内容が含まれています:


server {
 ...
 location / {
  try_files $uri /index.html
 }
}

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

webpack-dev-server

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


output.publicPath をカスタム値に設定します。


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


デフォルト

    デフォルトでは、output.publicPath 値は変更されません。webpack-dev-server のhistoryApiFallback 設定を設定するだけです:
  1. RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]

    HTML5 履歴を使用している場合。 API はおそらく 404 応答の代わりにインデックスを提供する必要があります。これは、historyApiFallback: true を設定することで実行できます

アプリケーションが HTML5 履歴 API を使用している場合、404 または質問リクエストの場合は、historyApiFallback: true を設定するだけです


カスタム値

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

Webpack 設定で Output.publicPath を変更した場合は、リダイレクト先の URL を指定する必要があります。ファイル内で Output.publicPath 値が変更されている場合は、リクエストのリダイレクトを宣言し、historyApiFallback.index を設定する必要があります。価値。


devServer: {
 historyApiFallback: true
}

Proxy

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

The proxy can be optionally bypassed based on the return from a function. The function can inspect the HTTP request, response, and any given proxy options. It must return either false or a URL path that will be served instead of continuing to proxy the request.

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


proxy: {
 '/': {
  target: 'https://api.example.com',
  secure: false,
  bypass: function(req, res, proxyOptions) {
   if (req.headers.accept.indexOf('html') !== -1) {
    console.log('Skipping proxy for browser request.');
    return '/index.html';
   }
  }
 }
}

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

解决问题

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


const PUBLICPATH = '/assets/'
...
proxy: {
 '/': {
  bypass: function (req, res, proxyOptions) {
   console.log('Skipping proxy for browser request.')
   return `${PUBLICPATH}/index.html`
  }
 }
}

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

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


historyApiFallback: true

相关推荐:

使用Django实现自定义404,500页面的方法

IDEA导入web项目详解(解决访问的404)

thinkphp制作404跳转页的简单实现方法

以上が反応ルーターのブラウザ履歴更新ページ 404 問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。