'how to deploy frontend(React.js) and backend(Node.js) in a single Heroku app

I have a parent folder named "app" and it has 2 children folders,

  1. "frontend"
  2. "backend"

obviously both have different package.json files. In order to deploy it to Heroku, we need package.json in the root folder, Can somebody explain how can I get that in the root folder?



Solution 1:[1]

A fullblown tutorial is far beyond the scope of a Stack Overflow answer, sorry to say.

In outline, what you do is this. You may need help from your team leader to get all this to work.

  1. Create a public directory in your backend app ... the one you'll deploy to Heroku.

  2. Put all your static frontend files in that directory.

  3. Put a line like this in your node express program.

    app.use(express.static('public'))
    
  4. Commit your public directory to your backend app repo.

  5. Tell your users to hit whatever.herokuapp.com/index.html or whatever the start page of your frontend app was.

  6. Copy the build instructions for your frontend into the toplevel package.json for your backend, and make them output to your newly created public directory.

  7. Delete the separate frontend repo, and (my opinion) never separate frontend and backend again unless it's an absolute requirement from devops or your team.

A more advanced approach might be to use git to create a subdirectory for your frontend code. But Heroku's deployment will be simpler when you combine front and back ends in a single repo.

(I wish influential teachers like Quincy Larson of freecodecamp.com would stop teaching people to create separated front and back ends.)

Solution 2:[2]

The directory structure I find gives the least issues when deploying to Heroku is the following:

App (root)
|
|
+---client
|   |
|   +---src
|   +---...
|   +---package.json (react)
|
+---models
+---routes
+---package.json (node)
+---Procfile
+---server.js

Your package.json (node) scripts should look something like this (keeping other custom scripts):

"scripts": {
  "start": "nodemon server.js",
  "heroku-postbuild": "npm install --prefix client && npm run build --prefix client"
}

Procfile should be:

web: node server.js

The package.json (react) scripts should stay relatively unchanged:

"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"

}

In the server.js, above app.listen(...):

app.use("/", routes);

if (process.env.NODE_ENV === "production") {
  app.use(express.static(path.join(__dirname, "/client/build")));

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

Notice that I'm declaring the use of my routes above, which has worked for me.

Hope this guides you...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 O. Jones
Solution 2 csarmiento