Home > Blockchain >  Stop statically served React app from calling server path
Stop statically served React app from calling server path

Time:09-29

My app has the default homepage at "/", and a contact page at "/contact". When I ran the react server(localhost:3000) and express server(localhost:8000) separately, the navigation between these pages works fine as handled by "react-router-dom" below.

Frontend React, Routing.tsx:

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Contact from "../pages/Contact/Contact";
import Main from "../pages/Main/Main";
import Error from "../pages/Error/Error";

function Routing() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/error" component={Error} />
        <Route path="/contact" component={Contact} />
        <Route path="/" component={Main} />
      </Switch>
    </BrowserRouter>
  );
}

export default Routing;

Now I built the react app using npm run build, and placed the "build" folder inside my backend express server to be served, as per deployment doc enter image description here

How can we prevent frontend navigation from calling the server routes?

More code below, thanks.

Backend Express, App.ts:

import express from "express";
import path from "path";

class App {
  private _app: express.Application;
  private readonly _port: number | string = process.env.PORT || 8000;

  constructor(controllers: any[]) {
    this._app = express();
    this.initializeControllers(controllers);
    this.initializeMiddleWares();
    this.initHostingReactUI();
  }

  public start() {
    this._app.listen(this._port, () => {
      console.log(`App listening on the port ${this._port}`);
    });
  }

  private initializeControllers(controllers: any[]) {
    controllers.forEach((controller) => {
      this._app.use("/api", controller.router);
    });
  }

  public initializeMiddleWares() {
    require("./src/middleware/express.middleware")(this._app);
  }

  public initHostingReactUI() {
    // I am aware that you can do "/*" below to catch all routes, but that doesn't solve my issue as it still calls the backend for every non-api routes that should be handled by frontend routing.
    this._app.get("/", (req, res) => {
      res.sendFile(path.join(__dirname, "build", "index.html"));
    });
  }
}

export default App;

Backend Folder structure with Build folder:

enter image description here

If needed:

Backend github source.

Frontend github source

CodePudding user response:

Do you mean navigate through the app? if not, navigating to the page by the URL or refreshing the page always will send a request to the server, which should return the app index.js.

All you need to do is to place the last route which is serving react (You can use app.get('*', .....) or placingapp.use((req, res) => {...}) without route).

In this case, when the request came to the server, the server will search for the route top-to-bottom, if the requested route is not api then it's will serve the client-side app.

CodePudding user response:

There are two ways to combine the routes between the frontend and backend:

If access from http://localhost:3000

You need to boot both frontend and backend.

In this case, all your backend request urls will start with http://localhost:3000 (if you didn't specify a base url). To solve this issue, add a line in the root of your client-side package.json file:

{
    "proxy": "http://localhost:8000"
}

This will redirect all the routes unknown to frontend to backend.

If access from http://localhost:8000

You only need to boot the backend.

Since React application is one-page application, which means there is only one html entry (index.html). Therefore, we need a route to serve the frontend routes in the backend:

// place this in the end after the other routes
app.get('*', (req, res) => 
    res.sendFile(path.join(__dirname, "build", "index.html"));
})

Now, the routing system will check if the route exists among the backend routes. If not, serve index.html, then check if the route exists among the frontend routes. Therefore, in the frontend you should guard the urls by returning a 404 page when not found.

  • Related