本篇文章主要介紹了react-router browserHistory刷新頁面404問題解決方法,非常具有實用價值,需要的朋友可以參考下
使用React開發新項目時,遇見了刷新頁面,直接存取二級或三級路由時,存取失敗,出現404或資源載入異常的情況,本篇針對此問題進行分析並總結解決方案。
背景
使用webpack-dev-server做本機開發伺服器時,正常情況只需要簡單使用webpack-dev-server指令啟動即可,但是當項目處於以下兩種情況時,往往需要有嵌套路由和非同步載入路由:
我們使用react-router這種路由庫建構單一頁面應用路由;
使用html-webpack-plugin外掛動態將載入js的3f1c4e4b6b16bbbd69b2ee476dc4f83a標籤注入html文件;
這時,存取localhost:9090是可以正常載入頁面和js等檔案的,但是當我們需要存取二級甚至三級路由或刷新頁面時,如localhost:9090/posts/92時,可能會出現兩種情況:
頁面載入失敗,傳回Cannot Get(404);
服務回應,但沒有傳回webpack處理輸出的html文件,導致無法載入js資源,第二種情況如圖:
那我們要怎麼處理才能正常訪問,各頁路由呢?部落客追蹤溯源,查找文件配置後解決了問題,這篇文章就是對整個解決問題過程的總結。
分析問題
發現問題後,我們就要開始分析,解決問題了,我們判斷這個問題一般是兩方面原因造成:
#react-router路前端由設定;
webpack-dev-server服務配置;
webpack-dev-server服務配置;
## react-router
因為前端路由更容易確定問題,更方便分析,而且對於react-router更熟悉,所以首先去查詢react-router路由庫相關配置信息,發現文檔中提到了使用browserHistory時,會建立真實的URL,處理初始/請求沒有問題,但是對於跳轉路由後,刷新頁面或直接訪問該URL時,會發現無法正確相應,更多資訊查看參考文檔,文檔中也提供了幾種伺服器配置解決方式:
Nodeconst 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
如果使用的是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
設定了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 responsesly , which can be done by setting historyApiFallback: true
#如果你的應用使用HTML5 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
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是在react-router中刷新頁面出現404問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!