mars / heroku-cra-node

⚛️ How to use create-react-app with a custom Node server on Heroku
MIT License
927 stars 226 forks source link

Express.js fetch error. Any API call returns react index.html #42

Closed vladi-strilets closed 4 years ago

vladi-strilets commented 4 years ago

Hi, after deploying on Heroku the node.js + create-react-app project, I'm getting an error with fetching my express routes, meanwhile, with the local deploy, it is working perfectly. My package.json scripts and express version:

"scripts": {
        "client": "cd client && yarn start",
        "server": "nodemon server.js",
        "build": "cd client && npm run build",
        "dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\"",
        "start": "node server.js",
        "heroku-postbuild": "cd client && npm install && npm install --only=dev --no-shrinkwrap && npm run build"
    },
    "dependencies": {
        "body-parser": "^1.18.3",
        "compression": "1.7.4",
        "cors": "2.8.5",
        "dotenv": "7.0.0",
        "express": "^4.16.4",
        "stripe": "6.28.0"
    },
    "devDependencies": {
        "concurrently": "^4.0.1"
    }

And my server.js is:

const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const path = require("path");
const compression = require("compression");

if (process.env.NODE_ENV !== "production") require("dotenv").config();

const app = express();
const port = process.env.PORT || 5000;

app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

if (process.env.NODE_ENV === "production") {
    app.use(express.static(path.join(__dirname, "client/build")));
    app.get("*", function(req, res) {
        res.sendFile(path.join(__dirname, "client/build", "index.html"));
    });
}

app.listen(port, error => {
    if (error) throw error;
    console.log("server running on port " + port);
});

// define routes
app.use("/api/search", require("./routes/search.routes"));
app.use("/api/origens", require("./routes/origens.routes"));

So, locally with yarn dev it works good, but on production, with axios({url: "/api/origens", method: "get"}) I'm getting the "client/build/index.html" as a response.data.

Am I doing something wrong? Thanks!

JacksonBates commented 4 years ago

This is an old issue, but assuming you haven't fixed it yet it looks like you need to declare those API routes above / before the app.get('*')...

My understanding is that when express is resolving the routes it looks for the first match - i.e. in this case everything routes to index.html. If you declare the wildcard index route after all other routes, then api routes shouldn't get swallowed up by the React route.

vladi-strilets commented 4 years ago

Got it! Thanks @JacksonBates