MERN Stack - Express and React on same port?

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-11 03:24:03

问题


I'm working on a project with the MERN (MongoDB, Express, React, Node) stack and I'm having issues when posting data from a form within a React component to an API endpoint defined in Node.js. When I submit the form the browser just shows a CANNOT POST error. I'm pretty confident that if I create an event handler for the form submit within React and handle the POST using a library such as Axios that I could get around this issue.

But ultimately I believe this problem is because the Node backend is running on a different port to the React front end. Is there a way that I can configure my stack so I can use a standard form POST and potentially have the FE and BE running on the same port?


回答1:


I see that you are running an un-ejected CRA. That means that when you run npm run start from your create-react-app folder you should have react running on port 3000, the default port.

First I would recommend keeping your server and client code into a separate folder with separate package.json files

Now let suppose you have this code in /server/index.js Its straight out of the express example but the route starts with /api and also will run on port 5000. This is very important and you will see why in a minute.

const express = require('express');
const app = express();

app.get('/api/hello', (req, res) => res.send('Hello World!'))

app.listen(5000, () => console.log('Example app listening on port 5000!'))

Now back into your /client folder where I will assume your CRA is, open package.json and add the following lines:

"proxy": {
  "/api/*": {
    "target": "http://localhost:5000"
  }
},

Try now to do a call the server from react with axios for example:

const helloFromApi = 
  axios
    .get('/api/hello')
    .then(res => res.data);

Hope it helps

UPDATE 10/21/2019

proxy field in package.json must be a string

"proxy": "http://localhost:5000"



回答2:


For developing add the following line to the package.json file

"proxy": "http://localhost:{your API port}/"

For production you can setup proxying in app (Express, Nginx, ...) which will serve your static files (React app, styles, etc). Usually using "/api/" mask for determination API request.




回答3:


But ultimately I believe this problem is because the Node backend is running on a different port to the React front end.

Okay,

MERN is fantastic. My only problem was I couldn't use Mongoose on the React side, I came across this issue and after a few hours, I found a better solution,

No need to put anything on package.json, no need to worry about CORS,

here's a working example of a user registration using mongoose (mongoose will never run on client side, don't waste time, the library modification is time consuming),

start your express server on a port, lets say 3030, and React runs on 3000,

on React side,

constructor(){ 
...
  this.server = server || 'https://my.ip.add.ress:3030'
...
}

register(username, password, signup = true) { 
return this.fetch(`${this.server}/server/register`, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                username,
                password,
                signup
            })
        }).then(res => { console.log(res);
            this.setToken(res.token) // Setting the token in localStorage
            return Promise.resolve(res);
        })
}

On Node.JS server (express) side,

Create a folder 'server' and create a file server.js,

var MongoNode   = require('mongoosenode')   // I created this package for just to test mongoose which doesn't run on React side, 
var cors        = require('cors');  //use cors for cross-site request

var options = {
        key     : fs.readFileSync('server.key'),
        cert    : fs.readFileSync('server.cert'),
    };

    /*
     * Cors Options
     */ 
    var whitelist = config.allowedOrigins //put https://my.ip.add.ress:3000 in the allowedOrigins array in your config file
    var corsOptions = {
        origin: function (origin, callback) {
            if (whitelist.indexOf(origin) !== -1) {
                callback(null, true)
            } else {
                callback(new Error('Not allowed by CORS'))
            }
        }
    }
    //specify the port
    var https_port = config.server.port || 3030;

    //use app or any route included to server.js
     app.post('/register', cors(corsOptions),function(req, res) {
        //Process requests
        console.log(req.body);  //see if request payload popping up
        var mn = new MongoNode('mongodb://username:password@127.0.0.1:27017/databasename')

        var user = mn.retrieveModel('User','User').then(async(res) => { 
           try { 
             user = res.model;
              console.log(user);
              user.username = req.body.username
              user.password = req.body.password
              user.token = token_str  //jwt web token to save browser cookie 
              user.save(function(err) {
                 if (err) throw err;
                 console.log('user saved successfully');
                 res.json({ success: true, token: user.token});
              });                  

           }catch(e) { 
             console.log(e);
           }
        })

        user.save(function(err) {
            if (err) throw err;
            //console.log('user saved successfully');
            res.json({ success: true , message: 'user saved successfully', token : user.token });
        });

    }

Voila! it's done easily after a few hours of reading.



来源:https://stackoverflow.com/questions/50591374/mern-stack-express-and-react-on-same-port

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!