Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

javascript - How to deploy node js app with react to heroku

I trying deploy my MERN app to heroku.

After build success on heroku doesn't see a API routes:

Steps: On localhost I run concurrently node server and client (create-react-app). Server on port 5000 and client on port 3000. After this I fetch from API routes /hotels Array with items and connect it to Redux store and display it.

Properly behavior:

Localhost: works fine

Heroku: broken (didn't connect with API)

This is my server.js file:

const express = require('express');
const path = require('path');
const app = express();
const http = require('http');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const passport = require('passport');
const morgan = require('morgan');
const keys = require('./API/config/keys');

//######### MODELS #########
require('./API/models/Users');

//######### SERVICES #########
require('./API/services/passport');

//######### MONGODB CONNECT #########
mongoose.connect(MONGO_CONNECT);

//######### ROUTES #########
const hotelsRoutes = require('./API/routes/hotels');
const countRoutes = require('./API/routes/count');
const topRoutes = require('./API/routes/top');

// Use routes
app.use('/hotels', hotelsRoutes);
app.use('/count', countRoutes);
app.use('/top', topRoutes);

app.use(morgan('dev'));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({extended: false}));

app.use(bodyParser.json());
app.use(
  cookieSession({
      maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
      keys: [keys.cookieKey]
  })
);

app.use(passport.initialize());
app.use(passport.session());

require('./API/routes/authRoutes')(app);

app.use(express.static('client/build'));

app.get('*', (req, res) => {
   res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});

const port = process.env.PORT || 5000;
const server = http.createServer(app);

server.listen(port);

Package.json (server):

{
  "name": "root-react-hotel-app",
  "version": "0.1.0",
  "main": "server.js",
  "scripts": {
    "client": "cd client && yarn start",
    "start": "node server.js",
    "start-api": "nodemon server.js",
    "dev": "concurrently "yarn start-api" "yarn client"",
    "build": "cd client && npm install && yarn build"
  },
  "devDependencies": {
    //
  },
  "dependencies": {
    //
  }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Since your express server is serving both your react bundle and your api routes, in:

app.get('*', (req, res) => {
   res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});

You need to protect your api routes in the 'app.get' when deploying to heroku (production mode). You can use a simple regex in order to serve all routes to your react bundle except '/api' (or whatever your api endpoint looks like, /API in your case above). It works running locally because you are running your api and react app on separate ports, not the same server.

Usually something like:

if (process.env.NODE_ENV === 'production') {
      app.get(/^/(?!api).*/, (req, res) => { // don't serve react app to api routes
        res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
      });
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...