文件结构
.root
|-client
| -build
| -node_modules
| -public
| -src
| -components
| -resources
| -data
| -images
| -templates
|-server
| -models
| -public
| -routes
| -server.js
服务器.js
//Required NPM Packages
const express = require('express'),
app = express(),
cors = require('cors'),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
methodOverride = require('method-override');
//MongoDB models.
const Product = require('./models/Product');
//Routes.
const indexRoute = require('./routes/index');
const demoRoute = require('./routes/demo');
const bootstrapTemplateRoute = require('./routes/bootstrapTemplate');
//Port.
const _PORT = process.env.PORT || 5000;
//Connect to mongoDB.
mongoose.connect({pathToMongoDB}, {useNewUrlParser:true, useUnifiedTopology:true});
//Setup body-parser.
app.use(bodyParser.urlencoded({extended:true}));
//Allow express/node to accept Cross-origin resource sharing.
app.use(cors());
//Set view engine to EJS.
app.set('view engine', 'ejs');
//Change views to specified directory
app.set('views', path.join(__dirname, '..', 'client','src','Resources','templates'));
app.use(express.static(__dirname+"/public"))
app.use(express.static("client/build"));
app.use(express.static("client/Resources/templates"));
//Setup method override.
app.use(methodOverride("_method"));
//register routes to express.
app.use('/', indexRoute);
app.use('/demo', demoRoute);
app.use('/bootstrapTemplate', bootstrapTemplateRoute)
//listen to established port.
app.listen(_PORT, () => {
console.log(`The server has started on port ${_PORT}!`);
});
module.exports = app;
问题
当我单击后退按钮或在我的浏览器栏中加载页面时,nodeJS 指出它无法获取该页面。我认识到前端和后端请求是不同的,因为 React-Router 通过它自己的 javaScript 处理路由,允许零页面重新加载,但是您如何实际解决 nodeJS/Express 上的问题?此外,当我转到 localhost:3000/demo 时,它会从我的 mongoDB 返回数据并以 json 格式呈现,而不是加载正确的页面。
目前正在使用以下 Nginx 基本路由配置处理 MERN 堆栈。
http{
server{
listen 3000;
root pathToRoot/client/build;
location / {
proxy_pass http://localhost:5000/;
}
}
}
events {
}
我相信问题出在我通过 express/nodejs 的路由中。我无法创建快速的特定路由并呈现正确的页面,因为 react 正在为我渲染它。我看了以下问题 反应路由器网址在手动刷新或写入时不起作用。我应该只做一个包罗万象并重新路由回主索引页面吗?这似乎会使书签无法使用。
编辑
以下是 2 个节点路由。
索引.js
const express = require('express'),
router = express.Router();
router.get("/", (req,res) => {
//Render index page.
res.render("index");
});
演示.js
const express = require('express'),
router = express.Router();
const Product = require('../models/Product');
router.get('/:searchInput', (req,res) => {
Product.find({ $text: {$search: req.params.searchInput}}, (err,foundItem) => {
if(err){
console.log(err);
}else{
res.send(foundItem);
}
})
})
router.get('/', (req, res) => {
Product.find({}, (err, foundItem) => {
res.send(foundItem);
});
});
module.exports = router;
我会尝试将您的开发文件夹与构建文件夹分开,因为一旦您开始运行react build
,它就会变得有点混乱。我使用的结构是:
api build frontend run_build.sh
api
文件夹包含我对快速服务器的开发,frontend
包含我对 react 的开发,build
是从run_build.sh
脚本创建的,它看起来像这样。
#!/bin/bash
rm -rf build/
# Build the front end
cd frontend
npm run build
# Copy the API files
cd ..
rsync -av --progress api/ build/ --exclude node_modules
# Copy the front end build code
cp -a frontend/build/. build/client/
# Install dependencies
cd build
npm install
# Start the server
npm start
现在在你的build
目录中,你应该有子文件夹client
它包含你的反应代码的构建版本,没有任何混乱。要告诉 express 使用某些路由进行 react,请在 expressserver.js
文件中添加以下内容。
注意在添加反应路由之前,请先添加您的快速 API 路由,否则它将不起作用。
// API Routing files - Located in the routes directory //
var indexRouter = require('./routes/index')
var usersRouter = require('./routes/users');
var oAuthRouter = require('./routes/oauth');
var loginVerification = require('./routes/login_verification')
// API Routes //
app.use('/',indexRouter);
app.use('/users', usersRouter);
app.use('/oauth',oAuthRouter);
app.use('/login_verification',loginVerification);
// React routes - Located in the client directory //
app.use(express.static(path.join(__dirname, 'client'))); // Serve react files
app.use('/login',express.static(path.join(__dirname, 'client')))
app.use('/welcome',express.static(path.join(__dirname, 'client')))
App.js
组件文件中的 reactApp
函数将如下所示,定义您刚刚添加的路由,告诉 express 用于 react。
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/login" render={(props)=><Login/>}/>
<Route exact path="/welcome" render={(props)=><Welcome/>}/>
</Switch>
</div>
</Router>
);
}
在组件文件夹下有用于login
和welcome
的组件。现在导航到http://MyWebsite/login
将提示 express 使用 react 路由,而例如导航到http://MyWebsite/login_verification
将使用快速 API 路由。