I'm currently working on a project using React (via create-react-app
) and JSONServer for the API.
I have a single Git repository structured as follow :
|-- client
|-- api
To work in a dev environment, I start both of the folders with npm start
in order to have http://localhost:3000 for the React app and http://localhost:3001 for the API.
This way (thanks to Axios) I can connect to http://localhost:3001/api to retrieve my content
import axios from 'axios'
export default axios.create({
baseURL: 'http://localhost:3001/api'
})
Everything works great so far.
Now I want to deploy my app and API to Heroku and this is where things get complicated.
So here's my questions and it would be very helpful to have some advice on what is the best way to handle it:
For the moment, I have a server.js
file at the root of my client's folder and a Procfile
with web: node server.js
to launch a server for the build. Then I fetch data with Axios from another Heroku app (which is actually the API app).
Any advice/help will be very appreciated! Thanks!
P.S.: here's my package.json ans server.js files for client and api
Client's server.js (at the root of client's folder)
const express = require('express')
const http = require('http')
const path = require('path')
const app = express()
app.use(express.static(path.join(__dirname, 'build')))
const port = process.env.PORT || '8080'
app.set('port', port)
const server = http.createServer(app)
server.listen(port, () => console.log(`Running on localhost:${port}`))
Api's server.js (at the root of api's folder)
const express = require('express');
const jsonServer = require('json-server');
const router = express.Router();
const server = jsonServer.create();
const mainRoute = jsonServer.router('db.json');
const middlewares = jsonServer.defaults({ noCors: false });
const port = process.env.PORT || 3001;
router.use('/api', mainRoute)
server.use(middlewares);
server.use(router);
server.listen(port);
Client's package.json:
{
"name": "portfolio",
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/core": "^10.0.28",
"@emotion/styled": "^10.0.27",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"express": "^4.17.1",
"google-spreadsheet": "^3.0.11",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-intl": "^4.6.3",
"react-lazyload": "^2.6.8",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"postinstall": "react-scripts build"
},
"proxy": "https://my-api.herokuapp.com/api",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"eslint-plugin-react": "^7.20.0",
"react-spring": "^8.0.27",
"standard": "^14.3.4"
}
}
Api's package.json:
{
"name": "json-server-heroku",
"version": "1.0.0",
"description": "Simple json-base database to deploy to Heroku",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"fetch": "node fetch-data.js"
},
"keywords": [
"json-server,heroku, node, REST API"
],
"author": "Jesper Orb",
"license": "ISC",
"dependencies": {
"google-spreadsheet": "^3.0.11",
"json-server": "^0.16.1"
}
}
I see you are using json server, so you don't need to use express to serve your static assets, instead you need to move your build folder to root level of the project and rename it as public
so that json-server will see it and serve it according to their markdown on github
api/package.json
and server.js
to the root level of your application.client/build
folder(after running npm run build from ./client) and rename it as public, add a heroku-postbuild script to the root package.json like this
"heroku-postbuild": "cd client && npm install && npm install --only=dev --no-shrinkwrap && npm run build && mv -v build/ .. && cd .. && mv build public"
client/.env.development
REACT_APP_BASE_URL=http://localhost:4000/api
client/.env.production
REACT_APP_BASE_URL=https://myapp.herokuapp.com/api
json-server
serve your static frontend files automatically.