首頁  >  文章  >  web前端  >  react-router browserHistory刷新頁面404問題如何解決

react-router browserHistory刷新頁面404問題如何解決

小云云
小云云原創
2017-12-29 16:18:343404瀏覽

使用React開發新專案時,遇見了刷新頁面,直接存取二級或三級路由時,存取失敗,出現404或資源載入異常的情況,本篇針對此問題進行分析並總結解決方案。本文主要介紹了react-router browserHistory刷新頁面404問題解決方法,非常具有實用價值,需要的朋友可以參考下,希望能幫助大家。

背景

使用webpack-dev-server做本機開發伺服器時,正常情況只需要簡單使用webpack-dev-server指令啟動即可,但是當專案處於以下兩種情況時,往往需要有嵌套路由和非同步載入路由:

  1. #我們使用react-router這種路由庫建立單一頁面應用路由;

  2. 使用html-webpack-plugin外掛程式動態將載入js的3f1c4e4b6b16bbbd69b2ee476dc4f83a標籤注入html文件;

##這時,存取localhost:9090是可以正常載入頁面和js等檔案的,但是當我們需要存取二級甚至三級路由或重新整理頁面時,如localhost:9090/posts/92時,可能會出現兩種情況:

  1. 頁面載入失敗,回傳Cannot Get(404);

  2. #服務回應,但沒有傳回webpack處理輸出的html文件,導致無法載入js資源,第二種情況如圖:

那我們要怎麼處理才能正常訪問,各頁面路由呢?部落客追蹤溯源,查找文件配置後解決了問題,這篇文章就是對整個解決問題過程的總結。


分析問題

發現問題後,我們就要開始分析,解決問題了,我們判斷這個問題一般是兩方面原因造成:

  1. react-router路前端由配置;

  2. #webpack-dev-server服務配置;









#react-router


因為前端路由比較容易確定問題,比較方便分析,而且對於react-router比較熟悉,所以先去查詢react-router路由庫相關配置信息,發現文檔中提到了使用browserHistory時,會創建真實的URL,處理初始/請求沒有問題,但是對於跳轉路由後,刷新頁面或者直接訪問該URL時,會發現無法正確相應,更多資訊檢視參考文檔,文檔中也提供了幾種伺服器配置解決方式:


Node


#

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)
在使用Node作為服務時,需要使用通配符*監聽所有請求,並返回目標html文件(引用js資源的html)。

Nginx

  1. 如果使用的是nginx伺服器,只需使用try_files 指令:

  2. 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官方文檔,部落客反覆看了幾遍,才看清楚了問題所在,這裡也分兩種情況:

沒有修改output.publicPath,即webpack設定檔中沒有聲明值,屬於預設情況;


設定了output.publicPath為自訂值;


點此檢視文件

##預設情況

預設情況下,沒有修改output.publicPath值,只需要設定webpack-dev-server的historyApiFallback配置:

###
devServer: {
 historyApiFallback: true
}
# ##If you are using the HTML5 history API you probably need to serve your index.html in place of 404 responses, which can be done by setting historyApiFallback: true########如果你的應用使用使用HT5 toryApiFallback: true#########如果你的應用程式使用HT5 history API,你可能需要使用index.html回應404或問題請求,只需要設定g historyApiFallback: true即可#########自訂值#########However, if you have modified output.publicPath in your Webpack configuration, you need to specify the URL to redirect to. This is done using the historyApiFallback.index option#########如果你在webpack設定檔中修改了output.publicPath 值,那麼你就需要聲明請求重定向,配置historyApiFallback.index 值。 ############
// output.publicPath: '/assets/'
historyApiFallback: {
 index: '/assets/'
}
######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跳转页的简单实现方法

以上是react-router browserHistory刷新頁面404問題如何解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn