我开发了一个MERN网络应用程序,该应用程序在本地计算机上托管时运行良好。将其部署到Heroku平台后,可以首先加载链接到索引页面的任何页面,但刷新后将显示error 404 nginx
。控制台不会显示任何错误。
我不确定是什么问题,因为在本地测试时,我运行了“ yarn run build && yarn start”,这会产生生产模型,并且可以在本地主机上正常工作。
Login.js(一个页面示例)
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import {Link, withRouter} from 'react-router-dom';
import Button from '@material-ui/core/Button';
import Navigation from './Navigation';
import Footer from './Footer';
import './Login.css';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
message: '',
language: 'JP'
};
}
getLanguage = (lang) => {
if (lang != this.state.language) {
this.setState({language: lang});
}
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const {email, password} = this.state;
axios.post('/api/auth/login', {email, password}).then((result) => {
localStorage.setItem('jwtToken', result.data.token);
const username = result.data.username;
localStorage.setItem('username', username);
localStorage.setItem('email', email);
this.setState((prevState, props) => {
return {message: ''}
});
// pass the username and email to the dashboard
this.props.history.push({
pathname: '/dashboard',
state: {
email: email,
username: username
}
})
}).catch((error) => {
if (error.response.status === 401) {
this.setState((prevState, props) => {
return {message: 'Login failed. Username or password not match'}
});
}
});
}
render() {
const {email, password, message} = this.state;
return (<div className="login-content">
<Navigation history={this.props.history} language={this.state.language} getLanguage={this.getLanguage}/>
{
(this.state.language === "JP")
? (
<div class="container">
<form class="form-signin" onSubmit={this.onSubmit}>
{
message !== '' && <div class="alert alert-warning alert-dismissible" role="alert">
{message}
</div>
}
<h2 class="form-signin-heading">ログインしてください</h2>
<div className="form-desc">
<p>メンバーになると、より包括的な分析のためのテスト結果が保存されます</p>
</div>
<label for="inputEmail" class="sr-only">メール</label>
<input type="email" class="form-control" placeholder="メール" name="email" value={email} onChange={this.onChange} required="required"/>
<label for="inputPassword" class="sr-only">パスワード</label>
<input type="password" class="form-control" placeholder="パスワード" name="password" value={password} onChange={this.onChange} required="required"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">ログイン</button>
<p>
メンバーではありません?
</p>
<p>
<Link to="/register">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
登録してください</Link>
</p>
</form>
</div>
)
: (<div class="container">
<form class="form-signin" onSubmit={this.onSubmit}>
{
message !== '' && <div class="alert alert-warning alert-dismissible" role="alert">
{message}
</div>
}
<h2 class="form-signin-heading">Please sign in</h2>
<div className="form-desc">
<p>Becoming a member stores your test results for more comprehensive analysis</p>
</div>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" class="form-control" placeholder="Email address" name="email" value={email} onChange={this.onChange} required="required"/>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" class="form-control" placeholder="Password" name="password" value={password} onChange={this.onChange} required="required"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
<p>
Not a member?
</p>
<p>
<Link to="/register">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
Register here</Link>
</p>
</form>
</div>)
}
<Footer/>
</div>);
}
}
export default withRouter(Login);
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var bodyParser = require('body-parser');
// configuration ---------------------------------------------------------------
// express application
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended': 'false'}));
app.use(express.static(path.join(__dirname, 'build')));
// database
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
mongoose.connect(process.env.DATABASE, {promiseLibrary: require('bluebird')})
.then(() => console.log('Mongoose connection succesful'))
.catch((err) => console.error(err));
// routes
var userInfo = require('./routes/userInfo');
var auth = require('./routes/auth');
var questions = require('./routes/questions');
var payment = require('./routes/payment');
app.use('/api/user', userInfo);
app.use('/api/auth', auth);
app.use('/api/questions', questions);
app.use('/api/payment', payment);
//
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development'
? err
: {};
// render the error page
res.status(err.status || 500);
res.send(JSON.stringify({error: err.status}));
});
module.exports = app;
auth.js
var mongoose = require('mongoose');
var passport = require('passport');
var settings = require('../config/settings');
require('../config/passport')(passport);
var express = require('express');
var jwt = require('jsonwebtoken');
var router = express.Router();
var User = require("../models/User");
router.post('/register', function(req, res) {
if (!req.body.username || !req.body.password || !req.body.email) {
res.json({success: false, msg: 'Please pass username, email and password.'});
} else {
User.findOne({ email: req.body.email }, function(err, user){
if (err) throw err;
if (user){
res.status(401).send({success: false, msg: 'Authentication failed. User has registered.'});
} else {
var newUser = new User({username:req.body.username, email: req.body.email, password: req.body.password});
newUser.save(function(err) {
res.json({success: true, msg: 'Successful created new user.'});
});
}
})
}
});
router.post('/login', function(req, res) {
User.findOne({
email: req.body.email
}, function(err, user) {
if (err)
throw err;
if (!user) {
res.status(401).send({success: false, msg: 'Authentication failed. User not found.'});
} else {
// check if password matches
user.comparePassword(req.body.password, function(err, isMatch) {
if (isMatch && !err) {
// if user is found and password is right create a token
var token = jwt.sign(user.toJSON(), settings.secret);
// return the information including token as JSON
res.json({
success: true,
token: 'JWT ' + token,
username: user.username
});
} else {
res.status(401).send({success: false, msg: 'Authentication failed. Wrong password.'});
}
});
}
});
});
module.exports = router;