将create-react-app部署到Github Pages后,链接返回404错误

36

我正在尝试将 create-react-app 部署到 GitHub Pages 上的相对路径,并绑定自定义域名。例如 www.example.com/myproject

我使用了 react-router-domreact-router-reduxreact-router-bootstrap

我已经在 packages.json 中设置了主页为 http://www.example.com/myproject(也尝试过 homepage = "."),并且还为我的历史记录配置了 basename:

...
export const history = createHistory({ basename: '/myproject' });
const middleware = [thunk, routerMiddleware(history)];
...
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
const store = createStore(rootReducer, initialState, composedEnhancers);
已部署的应用程序在 www.mydomain.com/myproject 上运行,我可以通过应用程序链接进行导航。
但是,如果我直接输入路径(例如www.example.com/myproject/account)或在子页面上进行浏览器刷新,就会遇到404错误。
长期目标是根据此答案所述,在开发和生产环境中配置不同的相对路径,但首先我需要在部署中使其正常工作。

你需要一个服务器端脚本来处理路由,例如响应所有端点使用相同的index.html。 - Rei Dien
4个回答

59

问题:URL在服务器端被评估

当你在浏览器的地址栏中输入一个新的URL或刷新页面时,浏览器会请求服务器(在这种情况下是GitHub页面服务器)以获取该URL。此时,客户端路由器(react-router)不能采取任何行动,因为它尚未加载到该页面。现在,服务器查找与/accounts匹配的路由(因为路由是在客户端完成的),并返回404

解决方案

如果您控制服务器,则可以为所有路由提供index.html。这在create react app文档“使用客户端路由提供应用程序”中有解释。由于我们在GitHub页面的情况下没有这种控制权,我们可以尝试以下方法。

简单解决方案

browserHistory更换为hashHistory。通过此更改,您的URL将从以下形式:

www.example.com/myproject/account

变成:

www.example.com/myproject/#/account

所以有点凌乱。

较难解决方案

让GitHub页面在所有请求上重定向到index.html。基本上,您必须在构建目录中添加404.html文件,并添加代码以重定向到index.html了解如何执行此操作的更多信息

Create React App也有关于GitHub页面中客户端路由的文档


这个链接提供了一些不错的建议链接。对我有效的是使用HashHistory - Dev Yego
1
谢谢。只需使用HashRouter而不是BrowserRouter,我的问题就解决了,现在每个URL都可以从外部访问。https://reacttraining.com/react-router/web/api/HashRouter - Makan
谢谢。只需将BrowserRouter替换为HashRouter即可解决我的问题。 - Ahmad
它能够工作,但是当我刷新网页时,又会出现相同的404错误,或者<a href>也无法工作。 - Ashish Kamble
在使用 HashRouter 替代 browserRouter 后,为什么 URL 中会返回 ' # '? - Aashish Kumar
显示剩余3条评论

18

解决此问题的最佳方法是创建一个 index.html 的副本,并将其命名为404.html 以进行生产构建。 要做到这一点,请将以下内容添加到 package.json 脚本中:

"build": "react-scripts build && cp build/index.html build/404.html"

1
但是当重新加载页面(例如“/blog”)时,应用程序显示主页(“/”),而不是(“/blog”)。 - Kernel James
你的路由器出了点问题。 - chrtx
这个解决方案是可行的,但每当你刷新页面时,即使页面已经正确渲染,你的浏览器仍会弹出一个烦人的“此页面似乎已丢失”的消息。 - Elle

2
由于浏览器可能尚未缓存路由代码,因此如果您访问索引之外的路由,则会导致404错误。
顺便说一下,如果有人使用ZEIT Now进行部署(虽然gh-pages也类似),我花了一些时间设法解决它。我决定为其他遇到同样问题的人写一篇文章来帮助他们。 https://itnext.io/fix-404-error-on-single-page-app-with-zeit-now-b35b8c9eb8fb

我按照你的文章操作,出现了以下错误信息:'now' 不是内部或外部命令,也不是可运行的程序或批处理文件。错误代码为 1。 - nishi

0

由于您无法控制服务器以从所有路由提供index.html,因此一种选择是使用类似react-snap的工具。它将您的React应用程序呈现为单独的.html文件,您可以将其发布到GitHub Pages。单独的.html文件仍然包括React应用程序作为其中的一部分,因此一旦页面加载完成,React路由将像往常一样接管。


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