快速路线在本地运行但不在生产环境中

问题描述 投票:0回答:1

我们目前正在部署一个静态 React 应用程序,由 NodeJS / Express 服务器通过 apache2 反向代理提供服务。应用程序索引工作正常,但如果页面不存在,我尝试重定向,这可以在本地主机上工作,但不能在远程服务器上工作。如果我去

myip/foo
,我会收到
cannot GET /foo

这是我的 server.js :

const express = require("express");
const app = express();
const port = 8080;
const bodyParser = require("body-parser");
const cors = require("cors");
const db = require("./src/models/db.models");
const compression = require("compression");
app.use(bodyParser.json());
app.use(cors());
//Disable x-powered-by header for security reason
app.disable("x-powered-by");
// use compression (gzip etc) for each request to increase perf
app.use(compression());
app.get("/login", (req, res) => {
  res.sendFile(__dirname + "/client/index.html");
});
app.get("/signUp/:id", (req, res) => {
  res.sendFile(__dirname + "/client/index.html");
});
// force: true will drop the table if it already exists (so drop all the data too)
db.sequelize
  .sync()
  .then(() => {
    console.log("Server Running ‍(*-*)");
  })
  .catch((err) => console.log("Error ¯_(ツ)_/¯", err));
require("./src/routes/user.routes")(app);
require("./src/routes/auth.routes")(app);
require("./src/routes/pageContents.routes")(app);
require("./src/routes/survey.routes")(app);
require("./src/routes/theme.routes")(app);
require("./src/routes/question.routes")(app);
require("./src/routes/surveyQuestion.routes")(app);
require("./src/routes/surveyHasUser.routes")(app);
require("./src/routes/answer.routes")(app);
require("./src/routes/surveyHasTheme.routes")(app);
// use static folder to render builded front react app
app.use(express.static("client"));
app.listen(port, () => console.log(`Listening on port ${port}`));

这是我的 app.js (前端),在后端文件夹中构建并设置

import './App.css';
import Login from './pages/login/Login.page';
import React from 'react';
import { BrowserRouter, Route, Redirect } from 'react-router-dom';
import Intro from './pages/questionnaire/Intro/Intro.page';
import Edito from './pages/edito/Edito.page';
import Cgu from './pages/cgu/Cgu.page';
import { Switch } from 'react-router-dom';
import Questionnaire from './pages/questionnaire/Questionnaire/Questionnaire.page';
import Remerciement from './pages/questionnaire/Remerciement/Remerciement.page';
import ListeQuestionnaire from './pages/liste/ListeQuestionnaire.page';
import ProtectedRoute from './components/utils/ProtectedRoute.component';
import AuthService from '../src/services/auth.service';
import LogOut from './components/utils/logOut.component';
import TableauDeBord from './pages/tableauDeBord/tableauDeBord.page';
import SignUp from '../src/pages/signUp/signUp.page';
function App() {
    return (
        <div className="App">
            <BrowserRouter>
                <Switch>
                    <ProtectedRoute path="/intro" component={Intro} />
                    <Route path="/signUp/:token" component={SignUp} />
                    <Route path="/login" component={() => (AuthService.isAuthenticated() ? <Redirect to="/" /> : <Login />)} />
                    <ProtectedRoute path="/questionnaire" component={Questionnaire} />
                    <ProtectedRoute path="/remerciement" component={Remerciement} />
                    <ProtectedRoute path="/listeQuestionnaire" component={ListeQuestionnaire} />
                    <ProtectedRoute path="/cgu" component={Cgu} />
                    <ProtectedRoute path="/logOut" component={LogOut} />
                    <ProtectedRoute path="/edito" component={Edito} />
                    <Route path="/:token" component={SignUp} />
                    <ProtectedRoute path="/" component={TableauDeBord} />
                </Switch>
            </BrowserRouter>
        </div>
    );
}
export default App;

最后这是我的 apache 配置文件:

<VirtualHost *:80>
#    ServerName domain.com
#    ServerAlias www.domain.com
    DocumentRoot "/www/html/360-nodejs"
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full
    AllowEncodedSlashes On
    ErrorLog "/var/log/apache2error.log"
    CustomLog "/var/log/apache2errorcustom.log" common

    <Proxy *>
            #Require all granted
     Order deny,allow
     Allow from all
    </Proxy>

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

Apache 日志显示,当我们调用

/:id
/signUp/:id
时,服务器已关闭,但服务器仍在运行

我可以直接链接到另一个路由,但是如果我刷新页面,我会收到 404,如果我将其写入不再有效的 URL 中,则会收到 404,所以我无法查询像 /:id 这样的直接 URL,因为我也收到了404

node.js reactjs apache express static
1个回答
-1
投票

嗯,像往常一样,我应该更好的 RTFD。 https://create-react-app.dev/docs/deployment/#serving-apps-with-client-side-routing

如果您使用在底层使用 HTML5 PushState 历史 API 的路由器(例如,带有 browserHistory 的 React Router),许多静态文件服务器将会失败。例如,如果您使用带有 /todos/42 路由的 React Router,开发服务器将正确响应 localhost:3000/todos/42,但服务于上述生产构建的 Express 则不会。

这是因为当 /todos/42 有新页面加载时,服务器会查找文件 build/todos/42 但找不到它。服务器需要配置为通过提供index.html 来响应对/todos/42 的请求。例如,我们可以修改上面的 Express 示例,为任何未知路径提供 index.html:

app.use(express.static(path.join(__dirname, 'build')));
-app.get('/', function (req, res) {
+app.get('/*', function (req, res) {
   res.sendFile(path.join(__dirname, 'build', 'index.html'));
 });

如果您使用 Apache HTTP Server,则需要在公共文件夹中创建一个 .htaccess 文件,如下所示:

Options -MultiViews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.html [QSA,L]

当您运行 npm run build 时,它将被复制到构建文件夹。

我修改了我的server.js并添加了.htaccess,问题解决了。

© www.soinside.com 2019 - 2024. All rights reserved.