使用 Express 的单页应用程序 React 路由 URL。但不要使用 create-react-app 或 Heroku 之类的部署服务
Posted
技术标签:
【中文标题】使用 Express 的单页应用程序 React 路由 URL。但不要使用 create-react-app 或 Heroku 之类的部署服务【英文标题】:single-page-application React route URLs using Express. But NOT using create-react-app or deployment services like Heroku 【发布时间】:2019-05-21 22:25:57 【问题描述】:我的问题很常见:我有一个单页 React 应用程序,一切正常,但如果直接导航或刷新 URL 子页面将无法加载。
我花了几个小时(也许几天)搜索,许多论坛帖子/文章/教程写的关于这个问题的前提是使用像 Heroku 或 Digital Ocean 这样的部署平台,它们要么为你做一些工作,要么可能有一些混淆了我无法解析的相关工作,以使其对我的特定应用程序有意义。
不涉及特殊部署平台的讨论总是假设我使用 create-react-app 创建了我的应用程序,但我没有。我试图在 create-react-app 中重新创建使单页应用程序路由正常工作的进程(npm build
被编程为使 node
从 packages/react-scripts/bin
运行 react-scripts.js
,但 react-scripts 中的代码。 Node.js 比我的技能水平高一点,而且似乎还涉及 create-react-app 的其他方面——再说一次,我没有使用过——所以我放弃了。)
在开始这个过程之前,我对后端编程知之甚少。现在我参加了关于 node.js 和 MongoDB 的课程(我现在意识到 Mongo 与我正在尝试做的事情完全无关)。我目前正在参加 Express 课程,但我仍然有点出海,我几乎可以肯定有一个非常简单的解决方案。
我希望有人可以:a)解释我缺少什么; b) 将我引导到可以解释但不使用特殊部署平台或 create-react 应用程序的来源;或 c) 只需告诉我我缺少的一两行代码(我很确定它最终只会是一两行)。
我使用 Gulp 作为我的任务运行器构建了我的网站,并且一切都在本地运行良好(例如,刷新并直接访问像 localhost:3000/about 这样的子页面 URL 有效)。
负责这个的 Gulpfile 代码是:
const browserSync = require('browser-sync');
const historyApiFallback = require('connect-history-api-fallback');
function bs()
browserSync.init(
server:
baseDir: './'
,
middleware: [historyApiFallback()]
)
;
您可能很明显——这是我的设置——当简单地将站点文件夹上传到 cPanel 文件主机并期望它像在本地一样工作时,尝试通过 URL 直接访问 React 路由将停止工作,但那时我并不知道更好。
我现在正在尝试使用 Express 来设置我的 server.js 文件,以使单页应用程序路由工作。我已经告诉节点在我的 package.json 中运行 server.js。这是我的 server.js 文件的样子:
var express = require('express')
var path = require('path')
var history = require('connect-history-api-fallback');
var app = express()
app.use(history());
app.use(express.static(__dirname))
app.get('*', function (req, res)
// I've fiddled with this part a million
//different ways but can't seem to get it to work
//because including lines like 'alert('WORKING') or
//res.alert('WORKING') in here never result in an alert
//pop-up when entering a URL
res.sendFile(path.join(__dirname, '/index.html'))
)
var PORT = process.envPORT || 8080
app.listen(PORT, function()
console.log('Production Express server running at localhost: ' + PORT)
)
最终我希望像 www.mysite.com/about/ 这样的 URL 从我的 React 路由器加载页面和“/about”路由,但此时我会满足于任何和所有直接 URL 请求只转发到www.mysite.com/index,我也尝试过但失败了。
也许最好像在和孩子说话一样说出你的答案。
【问题讨论】:
【参考方案1】:你现在找错地方了。请记住,React 是用户和浏览器之间的接口(除了您的内容分发网络 (cdn),但我们目前对此不感兴趣)。您的服务器与浏览器交互(React)。不是用户。您的快速服务器用于向您的 SPA 提供数据。路由由 React 控制。
正如您所发现的,直接路由不起作用,因为从技术上讲,您的网站只有一个 index.html
文件供 React 捎带。这意味着两件事:
-
React 必须能够解释不同的路由
指向您的域的每个可能的 url 都必须直接访问
index.html
。
带有react-router
的SPA路由
对于第一个问题,您需要明确的路由逻辑。这就是 npm 包 react-router
的用途。
修改您的域名托管服务商设置,使其始终指向index.html
,无论用户输入什么网址
其次,您必须设置您的域名托管服务商以正确路由。如果您访问除index.html
以外的任何内容,您将获得404
。您可以利用这一点并设置您的主机将404
直接重定向到index.html
。这有点老套,但事情就是这样完成的(除了哈希历史,我们可以稍后再讨论)。
绕过主机配置,只需要react-router
,使用hashHistory
如果您想回避主机配置修改,可以使用react-router
的hashHistory
而不是browserHistory
。它在您的域和任何其他路由之间创建/#/
,这使您可以回避index.html
404
路由。这样做的缺点是你会得到“丑陋”的网址。
my-website.com/#/a_route
my-website.com/#/another_route
祝你好运
【讨论】:
如果解决方案位于 react-router npm 包中,那么这将是一个真正的绿野仙踪,结束我的旅程......我确实在我的项目中使用了 react-router 包(实际上我使用了react-router-dom,但我的理解是它完成了 react-router 所做的一切。来源:github.com/ReactTraining/react-router/issues/…)。 npmjs.com 上这两个包的官方文档非常少。我知道我可以使用哈希,但正如你所说,它很难看。没有他们我不知道该怎么做,这也很可耻。 我会考虑设置我的域名托管服务商设置以将所有请求重定向到 index.html ...除非您有其他关于如何制作/学习使路由 URL 正常工作的提示? 据我所知,仅使用react-router
而不使用 hashHistory
是不可能的。您的网站基本上没有多个页面。一切都必须运行index.html
以上是关于使用 Express 的单页应用程序 React 路由 URL。但不要使用 create-react-app 或 Heroku 之类的部署服务的主要内容,如果未能解决你的问题,请参考以下文章
使用的vueelementUIvuexexpressmongoDB的单页应用