javascript - React-router URL,路由节点/快递和文件结构
问题描述
文件结构
.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 正在为我呈现它。我查看了以下问题React-router urls don't work when refresh or writing manual。我应该只做一个全面的并重新路由回主索引页面吗?这似乎会使书签无法使用。
编辑
这是2个节点路由。
index.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
文件夹包含我的 express server 开发,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 使用某些路由进行反应,请在 expressserver.js
文件中添加以下内容。
注意在添加反应路由之前先添加你的 express 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')))
组件文件中的 reactApp
函数App.js
将如下所示,定义您刚刚添加的路由,告诉 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>
);
}
在 components 文件夹下有 和 的login
组件welcome
。现在导航到http://MyWebsite/login
将提示 express 使用 react 路由,而例如导航到http://MyWebsite/login_verification
将使用 express API 路由。
推荐阅读
- clojure - 在 Clojure 中检查 core.async/sliding-buffer 中的元素
- makefile - 如何使用文件列表执行 Makefile 模式规则
- jquery - jQuery放大和缩小可滚动div,当所有内容可见时消除滚动
- batch-file - 将 .BAT 转换为 .SH
- c# - 带有 .Net 核心的 iTextSharper 使用 iTextSharpLGPLv2.Core
- java - 如何创建一个填充不同类型对象的 ArrayList?
- google-bigquery - BigQuery Standard SQL 使用 UNNEST 复制数据
- jquery - 在悬停时更改背景图像
- amazon-web-services - 将消息从 SNS 发布到 kinesis
- c# - EF Core 中的一些关系问题