javascript - 使用 Express API 和 ReactJS SPA 进行路由
问题描述
我最近在 Heroku 上使用 React 部署了一个站点。在浏览器的控制台中,我收到了 html 文本的输出,而不是我的用户界面 javascript。
我认为问题的根源在于我的 server.js 路由为我的 index.html 提供服务
服务器.js
// Allows us to place keys and sensitive info in hidden .env file
require("dotenv").config();
// Require Packages
const express = require("express");
const app = express();
const morgan = require("morgan")
const db = require("./models");
const routes = require("./routes");
const passport = require("passport");
const session = require("express-session")
const path = require("path");
const MySQLStore = require("express-mysql-session")(session);
require("./config/passport")(passport)
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
let options = {};
if (process.env.NODE_ENV === 'production') {
options = {
host: process.env.HOST,
port: 3306,
user: process.env.USER,
password: process.env.PASSWORD,
database: process.env.DB
}
} else {
options = {
host: 'localhost',
port: 3306,
user: 'root',
password: process.env.DB_PASSWORD,
database: 'tracker'
}
}
// Options for mysql session store
let sessionStore = new MySQLStore(options);
// Pass in mysql session store
app.use(session({
key: 'surfing_dogs',
secret: 'surfing_dogs',
store: sessionStore,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize());
app.use(passport.session());
app.use(morgan('common'))
// THIS IS REALLY IMPORTANT FOR ROUTING CLIENT SIDE
// We want to have our app to use the build directory
app.use(express.static(__dirname + '/client/build'))
// For every url request we send our index.html file to the route
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
app.use(routes)
db.sequelize.sync({ force: false }).then(() => {
let server = app.listen(process.env.PORT || 5000, function () {
let port = server.address().port;
console.log(`Server is listening on PORT ${port}`)
})
})
详细地说,我将此路由放在我的 server.js 中,因为我有客户端路由,并且我想欺骗浏览器始终为 index.html 提供服务
我想解决这个问题的另一个原因是我目前无法使用凭据登录我的网站。
这是前端明智的登录过程的一小部分。我的目标是基于登录状态,但不幸的是登录状态没有改变。
if (this.state.loggedIn === true) {
return (
<Router>
<Navbar user={this.state.user} logout={this.logout} />
<Switch>
{this.state.userType === 'administrator' ? <Route path='/' exact component={() => <AdminHome user={this.state.user} />} /> : ''}
{this.state.userType === 'instructor' ? <Route path='/' exact component={() => <InstructorHome user={this.state.user} />} /> : ''}
{/* Path for student profile based on it */}
<Route exact path='/student/:id' exact component={StudentProfile} />
{this.state.userType === 'student' ? <Route path='/' exact component={() => <StudentHome user={this.state.user} />} /> : ''}
<Route exact path='/settings' exact component={() => <Settings user={this.state.user} />} />
<Route component={NoPage} />
</Switch>
</Router>
)
} else {
return (
<Router>
<Switch>
<Route path='/' exact component={SplashPage} />
<Route path='/login' exact component={Login} />
<Route path='/signup' exact component={Signup} />
{/* Go to signup based on cohortID */}
<Route path='/signup/:id' exact component={CohortSignup} />
<Route component={NoPage} />
</Switch>
</Router>
)
}
希望那里有人可以帮助我!
解决方案
在查看了 server.js 的存储库后,您将所有到达服务器的流量(甚至是您自己的 api 请求)发送到前端。
首先确保您的服务器端路由以可区分的内容开头,例如
app.get('/api/*',(req,res)=>/*somecode*/)
这是因为如果您的服务器也是前端中的一条路由,那么您的服务器会混淆诸如“/ login”之类的内容,并且最终只会根据定义的时间来提供一个或另一个。
然后更新你的 server.js 以匹配它,它应该可以工作:
//API Requests handled first
require('./routes')(app);
//Non api requests in production
if (process.env.NODE_ENV === 'production') {
app.use([someProductionMiddleware()])
// Express will serve up production assets i.e. main.js
app.use(express.static('client/build'));
// If Express doesn't recognize route serve index.html
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(
path.resolve(__dirname, 'client', 'build', 'index.html')
);
});
}
推荐阅读
- css - 带背景的框阴影和兄弟元素
- r - R中数据框中列的字典样式替换
- python - 如何让 Scons 中的 SConscript 知道标头位置?
- kubernetes - 在 kubernetes 集群中运行的 thrift hiveservers 的反向代理
- ruby-on-rails - 如何避免 Rails 依赖破坏中的 N+1 查询?
- matlab - Matlab循环中的置换
- python - 在 SQLAlchemy 中,有没有一种方法可以象征性地创建一个真正创建两列的列?
- android - 知道何时以编程方式删除了应用程序
- python - 将二维数组作为元素传递给 sklearn.SVM
- ios - 未找到符号:_XRContextFromDetailNode