我可以为Github Pages网站使用react-router创建路由吗?

5
好的,我已经使用React和React-Router制作了单页应用,并将其推送到github页面上,但是当我刷新或在浏览器中点击返回时,我的所有路由都无法正常工作。当我本地提供服务时,我也遇到了同样的问题,但是当我按照这篇SO答案进行操作后,我创建了一个server.js文件,在每个路由上提供了一个静态HTML页面的重定向。下面是该文件的内容:
"use strict";
let express = require('express');
let path = require('path');


let app = express();

app.use(express.static('public'));

app.get('/contact', function(req, res){
  res.sendFile('public/index.html', { root: __dirname });
})

app.get('/about', function(req, res){
  res.sendFile('public/index.html', { root: __dirname });
})

app.get('*', function(req, res){
  res.sendFile('public/index.html', { root: __dirname });
})

app.listen(8080, function(){
  console.log('Listening on port 8080!')
})

现在,我的问题是,当我将项目推送到github页面时,所有这些逻辑都被忽略了,github的路由接管了该页,我面临着无法刷新或直接访问/contact或/about的相同问题。我知道看起来像是一个明显的问题,因为github页面设计用于只托管静态站点,但我见过人们暗示使用其他方式创建每个路由的静态页面,例如这篇reddit帖子中的答案,但我不知道如何做到这一点。
我还应该提到,因为我已经在user-name.github.io上有一个站点,所以这个站点正在user-name.github.io/projects上托管,使其成为我的/路由。我不知道这是否有任何区别,我只是觉得我应该提一下。
我想我已经尽力尝试成功在gh-pages上托管它了,我知道有类似Single Page Apps for GitHub Pages的项目可以尝试解决这个问题,但我只是想看看是否有人在不使用它之前就已经成功地完成了这个项目。
FYI,这是我的app.js(包含路由逻辑):
import React, {Component} from 'react';
import {render} from 'react-dom';
import {Router, Route, browserHistory, IndexRoute} from 'react-router';
//Import custom components
import About from '../components/about.js';
import Contact from '../components/contact.js';
import Sidebar from '../components/sidebar.js';
import Imagelist from '../components/image-list.js';


  render(
      <Router history={browserHistory}>
        <Route path="/" component={Sidebar}>
          <IndexRoute component={Imagelist}/>
          <Route path="/about" component={About}/>
          <Route path="/contact" component={Contact}/>
        </Route>
      </Router>,
      document.getElementById('content')
    );

任何帮助都将不胜感激,如果需要的话,我很乐意提供更多代码。

Express是一个后端框架,用于编写API路由...你想通过gh静态页面实现什么目的?你想让gh页面指向另一个域中的API吗? - Lucas Katayama
我使用了 Express,因为另一个 SO 回答建议使用它,但是我知道当我将其推送到 gh-pages 时,不能包含任何此逻辑。只是想看看是否有关于为每个路由创建静态页面的建议。 - Maxine Ellah
5个回答

8

我认为你需要将你的browserHistory更改为hashHistory.. 这样你就可以在gh上使用它... 它将路径从/home更改为#/home


1
谢谢!那个完美地解决了问题。我读到 hashHistory 不推荐在生产环境中使用,但是现在来说,它是一个很好的折衷方案,因为 browserHistory 需要我配置服务器,而在 gh-pages 上托管时这是不可能的。 - Maxine Ellah

5
除了使用建议中提到的hashHistory之外,还有另一种解决方法。请看这里
基本上,您需要创建一个伪造的404.html文件,其中包含将请求路径转换为查询字符串并将浏览器重定向到带有附加到URL的查询字符串的索引页面的脚本。加载索引文件后,从查询字符串恢复原始路径,并且ReactRouter会捕捉更改。
这是一个不错的解决方案,但并不适用于生产环境。

4
如果您正在使用create-react-app(我没有在其他环境中测试过),您可以使用browserRouter,您需要向带有此环境变量的组件传递一个basename属性:process.env.PUBLIC_URL
您的路由器现在应该是这样的:
<BrowserRouter basename={process.env.PUBLIC_URL}>
  {/* routes */}
</BrowserRouter>

如果需要更多信息,您可以查看这个Github讨论帖

在路由定义中使用process.env.PUBLIC_URL,以便在开发和部署后都能正常工作。例如:<Route exact path={process.env.PUBLIC_URL + '/'} ... /> 这将在开发中为空,在生产中则为...(从主页推断)。


有人知道这个是否可以在不使用create-react-app的情况下工作吗?我正在使用parcel。 - static_null

3
为了扩展Jildert的答案,我也做了同样的事情 - 在将页面部署到GitHub之前将index.html复制到404.html,这样就可以正常工作了。
因此,我刚刚更新了package.json的预部署部分,包括这个复制操作,现在使用BrowserRouter可以正常工作了。
"predeploy": "npm run build && cp build/index.html build/404.html",
"deploy": "gh-pages -d build"

2

我找到了一种解决方法,不需要使用HashRouter。我创建了一个小的node脚本,在我的部署脚本之前调用它,创建一个404.html文件,其内容与index.html相同。如果您在react-app中刷新页面,则Github页面会提供该文件。

const fs = require('fs')
fs.copyFile('build/index.html', 'build/404.html', (err) => {
  if (err) throw err
  console.log('index.html was copied to 404.html')
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接