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

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.

Related

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!

How can I deploy Next js app on cpanel hosting

I am trying to deploy next js app on cPanel. I have installed node and npm on it.
How can I deploy the next js app on this set up?
I am getting the following error while trying to build the app on cpanel terminal:
Unhandled rejection TypeError: child.send is not a function
You'll need root privileges. If you've got them you can remote into your server via SSH and run the npm commands there. Then it should work. I.e, from console:
ssh user#serverip
cd /path/to/appdirectory
npm run start
There are some options to deploy NextJS app in CPanel:
You just deploy serverless app (without NodeJS) in CPanel. NextJS has provided a syntax like next export to producing optimized frontend files.
New version of CPanel already has entry point for your nodejs application:
Specify your server file on that field.
You should run next export to make static html and js files in out you can directly upload it to Cpanel as normal html website
you can run npm run export or yarn export by adding
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"export": "next export"
},
these in package.json
Next.js applications should run fine on a web hosting provider using cPanel, but running the default next.js server tends to exceed process count and memory quotas applied by those types of providers.
However you can make hosting next.js apps work if you build a production version of your app elsewhere and then use a custom server to call your next.js app to handle incoming requests.
I describe the process to deploy a very basic application as a subsite on my website here - https://www.watfordconsulting.com/2021/02/08/deploy-next-js-applications-to-a-cpanel-web-host/
All you really need to do is run next export and put the contents of the out folder in the public_html folder or /var/www/html/, /sites-available/, etc, depending on setup.

'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

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

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

Trouble using grunt connect server on heroku

All the tutorials I can find use some kind of app.js to run their node server on heroku.
I have already configured my grunt - connect task to use modRewrite for my single page app so that all requests simply return index.html. So it would be convenient for me to somehow just have heroku run my grunt dist once it npm installs.
I have tried adding this line to my package.json
"scripts": {
"postinstall": "echo postinstall time; ./node_modules/grunt/lib/grunt.js dist"
}
But I think there is something wrong with my path, because it doesn't work. I get a Permission denied error.
I also tried using a simple app.js express server (even though I would have to re-figure out how to do the modRewrite) -- but that failed somewhere along the line - heroku was looking for an index.js, which I don't have.
Thanks!
The solution I ended up with is a simple connect server using the same modRewrite code from my grunt task:
var connect = require('connect');
var modRewrite = require('connect-modrewrite');
var app = connect()
.use(modRewrite(
['^[^\\.]*$ /index.html [L]']
))
.use(connect.static('./dist/'))
.listen(process.env.PORT || 3000)
And the following Procfile:
web: node app.js

Categories