how do you start an express server with react on heroku? - javascript

I have managed to get my app working on heroku and I can hit the url and it loads successfully.
the problem is this is just the React frontend (locally I fire up on port 3000). I then also use an express node server as my backend for my api end points and then firebase as my data. when running locally I have been firing it up on 3007. however, I've just deployed and it's running the frontend but none of the API calls are being made (I presume it has not started the server)
how can I link the 2 up or tell heroku to run the other server command as well?

Imagine you have folder structured
-main folder
--client folder
--server stuff
try writing in server's package.json
"scripts": {
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
}
then deploy project to heroku from server folder's level
this will build your client during the time you're deploying your whole project
#edit
also add
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
const path = require("path");
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
to server's index.js file

Related

React & Node JS deployment on Apache server

I am trying to deploy my react app with node js as a backend on apache server on a shared hosting. My folder structure is lke following:
client //frontend folder along with build folder inside it "created
by npm run build"
config
controllers
models
node_modules
routes
package.json
package.lock.json
server.js
I have checked numerous tutorials and articles on the internet but failed to deploy it. Do I need to create ".htaccess" file? Can anyone guide me how to deploy it properly.
My server.js code:
// ROUTES
app.use("/api/sms", sms);
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "/client", "build", "index.html"));
});
//CONFIGURE PORT
const PORT = process.env.port || 5000;
const server = app.listen(PORT, () =>
console.log(
`Server running in "${process.env.NODE_ENV}" mode on port "${PORT}"`
)
);

Deploy Node.js Restfull API and Vue.js app at the same time

I want to deploy Node.js express API and Vue.js app in the same domain with Vercel in one project.
I have one Vue.js app in root folder and i have another folder in my root folder like ./api.
I tried this script in my package.json file(In my Vue.js app.):
"serve": "vue-cli-service serve && cd api && npm run start".
This is my Node.js app's package.json script:
"start": "node index.js"
But it not works. (I know the reason of "why it doesnt work".)
How can i deploy these 2 apps in the same project?
(So i want a API works like: example.com/api/urls)
Vercel is a serverless platform, while your usage of Express is "stateful", meaning you start a long-running server process that listens for requests. Serverless, on the other hand, consists of short-running processes that spawn as needed to handle requests.
Check out this guide for using Express with Vercel: https://vercel.com/guides/using-express-with-vercel
The simplest solution is to put your entire Express app into a single serverless function (even though this is an anti-pattern):
// /api/index.js
const app = require('express')()
const { v4 } = require('uuid')
app.get('/api', (req, res) => {
const path = `/api/item/${v4()}`
res.setHeader('Content-Type', 'text/html')
res.setHeader('Cache-Control', 's-max-age=1, stale-while-revalidate')
res.end(`Hello! Go to item: ${path}`)
})
app.get('/api/item/:slug', (req, res) => {
const { slug } = req.params
res.end(`Item: ${slug}`)
})
module.exports = app
And ensure you set up a rewrite in your vercel.json:
{
"rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
}
(these code snippets are taken directly from the guide linked above – I highly recommend following it!)
The better, serverless, approach would be to split your Express routes into their own serverless function that can be called on-demand.
Additionally, your "serve" script starting the API is unnecessary, as the top-level API directory is zero-config with Vercel. You can simply use "serve": "vue-cli-service serve".

Deploying React (3000) and Express (8000) app on the apache server

I have created a React+Express application using the commands npx create-react-app client for React and npx express-generator api for the express backend. Both client and API are under the same folder application.
The react application is running on the port 3000 and I have changed the port of express app to use port 8000 in the /bin/wwww.
In the express application I have crated a route in routes/testAPI.js,
router.get("/", function(req, res, next) {
res.send(“API is working properly”);
});
And in app.js file I have used the route to handle request,
let testAPIRouter = require("./routes/testAPI");
app.use("/testAPI", testAPIRouter);
Now in the react application inside the App.js file I have called the API and updated the content of <p>{this.state.apiresponse}</p>.
App.js file,
class App extends React.Component{
constructor(props){
super(props);
this.state = {
apiResponse : "",
}
}
apiCall = () => {
fetch("http://localhost:8000/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: res }));
}
componentWillMount = () => {
this.callAPI();
}
render(){
return(
<div>
<p>{this.state.apiResponse}</p>
</div>
)
}
}
My issue is to deploy this application on an apache server. As I'm running the express and react at different ports(3000 and 8000). I can build the react app using npm run build which will create static build files for react. But, how can I build the express app to use with react?
Is it so moving the express files to the server and always run the application there at port 8000?
I have successfully abled to run both at time using concurrent. I can run the application using npm run dev. But how to build the application and serve from apache?
Thanks in advance.
In the package.json of your react app use proxy
"proxy": "http://localhost:8000"
and use only the routes not base url to fetch
fetch("/testAPI")
Now copy React App Folder to your Express folder
and add this scripts to your package.json of Express
"scripts": {
"client-install": "npm install --prefix reactapp",
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix reactapp",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
Now run
npm run client-install
for only one time And run
npm run dev
to run both server and client
I appreciate all the answers I have received. So as an addition to the answers I have received I would like to mention how I moved the build into production.
1. npm install -g pm2
2. sudo chmod 755 /server/build/server.js (build file)
3. sudo pm2 start /server/build/server.js (Adds to pm2 task)
4. sudo pm2 startup systemd
And I have created a new virtual host in /etc/apche2/sites-available/nodeapp.conf and enable these apache modules
sudo a2enmod proxy && sudo a2enmod proxy_http
<VirtualHost *:80>
ServerName localhost(can be domain)
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
<Location /node>
ProxyPass http://127.0.0.1:3001
ProxyPassReverse http://127.0.0.1:3001
</Location>
<Directory "/project/server/build">
AllowOverride All
</Directory>
</VirtualHost>
Now enable the site by sudo a2ensite nodeapp.conf. Reload the server and hit localhost/node and boom!
Incase if you are getting any blank screen error make sure add the below in react's package.json. "homepage":"http://localhost/node".
https://www.ionos.com/community/server-cloud-infrastructure/nodejs/set-up-a-nodejs-app-for-a-website-with-apache-on-ubuntu-1604/
You need to modify your react application. Use Env variables to use diffenrent URLS. Define your base url as ENV.
After a build it's just simple HTML, CSS, JS application you can deploy it on sub path as well.
ex. https://example.com/website
There is no need to deploy react on port or with Express.
But if you want to achieve something like this what you can do is
prepare a build, put it in express views folders and serve your react application from Express.

Deploying app to google app engine and want to start api and client

Following this tutorial to get an api and client on google cloud platform:
https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together-c5798926047c/
I have a root dir with an /api and /client inside it
the /api package.json has the following script
"scripts": {
"start": "node ./bin/www"
},
the /client package.json has the following script
"scripts": {
"client-install": "npm install --prefix client",
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
When I try to deploy it says:
Step #0: Application detection failed: Error: node.js checker: Neither
"start" in the "scripts" section of "package.json" nor the "server.js"
file were found. Finished Step #0
I'm thinking it can't find the scripts? What is the best approach to start my api and client at the same time when I deploy?
My supposition is that the reported problem is generated by the fact that in root directory there is no package.json file. You could try to add one in root directory to handle stuff in app and client directories, but...
... but a taken a look to the tutorial you used and I found some things I don't like, so you want to give you some suggestions. I recently developed a simple tool to visualize charts about covid-19 diffusion in Italy, it uses same structure as your app with different approaches. The main difference is I deploy it in a VPS and I use external tool to launch it so in my package.json file there is not the script command to launch it in prod. It is something like:
cd client && npm install && npm run build && cd .. && npm install && node server.js
You can take a look to github repos to get ideas, but I'm going to explain the main differences.
server stuff (with package.json) is in root directory (simply this could solve your problem)
as per other answers, you need to add two lines to your express app to serve the built client as static files:
I suggest to use proxy features rather than cors package.
In your express app:
// At the begenning, with other middlewares
app.use(express.static(path.join(__dirname, "client", "build")));
// As last, to substitute any 404 with your client home page
app.get("*", (req, res) => res.sendFile(path.join(__dirname, "client", "build", "index.html")));
I don't know which kind of data you are going to treat, but CORS is a sort of protection you should never disable (by cors package), at least as it is possible. More than this, once you'll be able to solve the reported problem, I'm afraid that following part from the tutorial you used will not work, as it will try to fetch APIs from your app users's localhost:9000.
callAPI() {
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: res }));
}
To both enable CORS and solve fetching from localhost problem you should use proxy feature. In your client package.json file just add:
"proxy": "http://localhost:9000/",
This makes your webpack dev server to proxy calls it can't handle to your dev server, than changing your client fetching function to:
callAPI() {
fetch("/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: res }));
}
it will automagically works both in dev and prod envs and let you to enable back CORS.
Hope this helps.
Well in that tutorial that guy creates the react app using create-react-app and because of that I don't know why you have in the 'start' command in your second package.json the following command 'node server.js'. You should have "start": "react-scripts start", that won't fix your problem but I'm not sure if server.js another server or what.
Anyway I'll try to help you, first 'create-react-app' creates an app which internally uses webpack-dev-server which is cool for developing, but in order to deploy your app you need to run this command
npm run build
After that you will have a folder called 'build' with your react app. Then you need to copy that folder and go to your server project and paste the
'build' folder there. Once you finish that you need to add the following code to tell your server that you want to serve static files
app.use(express.static(path.join(__dirname, 'build')));
And you also need to add the route
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
Now you can test it locally running only your server and the '/' path should take you to the react app. Once you know that is working, you can deploy ONLY that server with the build folder and just one package.json to google app engine.
I hope helped you!

'serve' is not recognized as an internal or external command to run react app

serve has been installed globally using npm install -g serve command and It works locally, but deploying to a Windows server gives the following error:
"serve" is not recognized as an internal or external command
How to fix this error? Also, what is the use of the server.js file in a react project, and how does it help with deployment?
npm serve is installed globally please click here to see the image
I know that running npx serve -s build should work. I had the same problem as you. The npx command works for me. If you have npx problems, check your version of nodejs. I'm running 10.16.2 (so that we're on the same page). https://www.npmjs.com/package/serve
The rest of your question is relative to the rest of your set up. I don't have a server.js file of my own (there are some node_module server.js files, is that what you mean)?
As I understand a create-react-app, npm run start will allow you to run your application locally. I don't need serve -s build for that.
I used an amplify create react app. For an amplify application, I just run amplify publish and my application's build directory is sent to an S3 bucket for me. If you don't have that configuration, and you want the quick and dirty answer... just take the contents of your build directory in your react application and drop those files on your web server. That should get you 90% of the way there (mind the default page that renders).
Serving React Files
Basic Exapmle:-
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(9000);
For your base path in the domain serve the index.html you fetched from your build process.
If you need more info :- https://create-react-app.dev/docs/deployment

Categories