Azure: Connect/Proxy Frontend (React) to Backend (Express/node.js) - javascript

I am currently trying to connect a frontend (React) to a backend (Express/nodejs) within Azure App Services. I am using Windows, since "Virtual applications and directories" are currently not available for Linux. However, according to my research, that is necessary in this case.
Backend sample: server.js
const express = require('express');
const app = express();
const port = 3003;
require("dotenv").config(); // For process.env
[...]
app.get("/api/getBooks", async (req, res) => {
const books = await Books.find();
res.send(books);
});
Frontend sample: App.js
const getBooks = () => {
axios.get('/api/getBooks')
.then(res => {
setBooks(res.data);
console.log("Got books: ")
console.log(res.data);
})
.catch(err => {
console.log(err);
})
}
Azure: Folder structure
site/server/server.js (Express)
site/wwwroot/index.html (React)
I successfully executed "npm install" via "Development Tools/Console".
The two are already connected via Virtual applications in Azure by using the following configuration.
Virtual applications
The app generally loads succesfully. However, the connection to the backend is not working.
How can I start the node.js server now on Azure and make the proxy working?
I tried to start the server via "node server" on the console. But this does not seem to be working.

I discovered two possible ways to solve this issue.
Assuming you have a client (client/App.js) and a server (server/server.js).
Serve the React App via node.js/Express
Based on the above architecture, a little bit of structure needs to be changed here. Because the React app is no longer output through its own server, but directly through Express.
In server/server.js, the following function must be called after express is declared.
app.use(express.static("../client/build"));
After defining some endpoints to the APIs, the last API node to define is the default route - the static output of the React build.
app.get("/", (res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
Using an FTP client, you can now create the /client/build directory that will contain the built React app. Of course, another directory structure can be used.
The client files from the built React app are then simply uploaded there.
The deployment from the server is best done via Visual Studio Code and the Azure plugin.
In the above structure, /server would then be deployed to your in the Azure extension (Azure/App Services --> Right click on "myapp" --> Deploy to Web App ...)
Create two App Services
For example: myapp.azurewebsites.net & myapp-api.azurewebsites.net
myapp must simply contain the built React app (/build) in the wwwroot directory. This can be achieved via FTP.
The deployment from the /server to *myapp-api is best done via Visual Studio Code and the Azure plugin.
In the above structure, /server would then be deployed to myapp-api in the Azure extension (Azure/App Services --> Right click on "myapp-api" --> Deploy to Web App ...)
Also worth mentioning is that CORS should be configured, so that API calls can only be made from myapp.azurewebsites.net. This can be configured in the Azure Portal.
Occasionally the node dependencies have to be installed afterwards via the SSH console in the Azure Portal. For me it sometimes worked automatically and sometimes not.
To do this, simply change to the wwwroot directory (of the /server) and execute the following command.
npm cache clean --force && npm install
Combine this with React Router
React Router is usually used with React. This can be easily combined with a static-served web app from Express.
https://create-react-app.dev/docs/deployment/#other-solutions
Excerpt
How to handle React Router with Node Express routing
https://dev.to/nburgess/creating-a-react-app-with-react-router-and-an-express-backend-33l3

Related

Do I need node.js (express) to deploy an Angular App to Heroku?

Can I run my Angular App (build with ng build --prod) only with node.js / express on Heroku?
For my understanding, Angular in production does not need a node.js server but can run with only the generated static files (and some configuration). You can run it on a node.js server/express but it's not mandatory.
So far, in most of the tutorials I found on Google regarding Deploying an Angular App on Heroku, the instructions always setup a server.js file with express in the Angular app and there in the package.json there is often something like a postinstall or heroku-postbuild script with a ng build --prod command.
I guess, I'm mixing some concepts or have general misunderstanding of deployments of Angular Apps on Heroku.
No, You can also create a simple http-server and host the application. However, this won't help you to understand how your application is being server. Express-node server is a light weight and can help you define your routes.
You can also redirect any https request on this server.
const forceSSL = function() {
return function (req, res, next) {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect(
['https://', req.get('Host'), req.url].join('')
);
}
next();
}
}
app.use(forceSSL());
You can also use Docker to run angular app on Heroku.

Is there anyway that I can get the running port?

I`d like to show in my React application the running port of the local server, is there any way to get it programmatically? The running port may defer if something is already running on the default port of create-react-app.
create-react-app is a React toolchain, which packages some useful tools together to let you dive into development without any initial setup. Local development server is a part of that toolchain, it's only purpose is to serve static files your react app needs.
Sure, create-react-app lets you configure some options with environment variables but it is not meant to serve as backend for your react application.
You can achieve this with your own backend by writing an endpoint to get the server port but for the local server I don't think it is possible.
This functionality is not available since React App and Local server are running independently.
However, your server port will be available when you start the server. So you can have another API that will simply fetch the port of the server and that can be displayed accordingly.
Something like this on the server.
app.get('/server/port', (req, res) => {
return res.json({port: server.address().port})
})
where your server is started at
const server = app.listen(20000)
In the react app, you can have the fetch request like this
fetch('http://localhost:20000/server/port')
.then(response => response.json())
.then(data => console.log(data));
// you will have the port no. in data.port
This will be helpful to you.

How to start node.js server on Azure Web App service?

I have a create-my-react bootstrapped application that is essentially a website that uses some FETCH API calls to a external API and it is deployed and works fine.
However, I added my own Nodejs backend, by creating a server and using using express for the routes/middleware. Everything works fine locally. I can hit my internal API endpoints (localhost:3000/myapiurlhere) and it performs an action on a database.
I have to run npm start to start up the create-my-react-app locally and then manually run the node server by node src/server.js then my internal API works.
The Azure Web App service is basically a preconfigured server with the Node RUNTIME on it, and it only seems to give you access to the D:\home\site\wwwroot folder (Windows server).
Do I need to find a way to run node server.js command on the server to start my node backend, or should it be running automatically? Also, I'm using create-my-react-app and npm run build , so it creates a build folder with a nested static folder.
I have started up REST APIs on Java on my Linux Ubuntu servers before but never on an App Service like Azure. How can I achieve what I'm trying to do?
Here is my server.js file:
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3001;
const server = http.createServer(app);
server.listen(port);
You dont have to do anything special, Have you followed this page on how to deploy basic nodejs app on Azure AppService?
One additional thing you need to do is that pass the Node version on appsettings of the appservice.
WEBSITE_NODE_DEFAULT_VERSION for the setting key.

how to share environment variables between react app and express js server hosting it as static site

I have a react app hosted as static site under express server project in a folder called client/build. I have some oauth redirect uris that point to express server also points to for token retrieval later. My react-app redirects user to oauth endpoint which my express server env variables also refer to.
` //express .env :
process.env.HOST=localhost
process.env.PORT=port
process.env.OAUTH2URI=example.com
`
` //react .env :
process.env.REACT_APP_HOST=localhost
process.env.REACT_APP_PORT=port
process.env.REACT_APP_OAUTH2URI=example.com
`
when i run my express app, how can the react app refer to the same host and port my express server app is using ?
Can i not refer the common env variables from express app into react app without duplicating with different names.
I tried a lot of things, of which none seemed to work.
What I did as a workaround for this is make an API in Express which will be called by the front-end and will forward the env vars.
Something of the sort:
app.get('/getEnvironmentVars', (_, res) => {
res.json({ ENVIRONMENT: process.env })
})
Then you just fetch it in the front-end code like:
export async function getEnvironmentVarsFromExpress() {
return await fetch('/getEnvironmentVars').then((res) => res.json())
}
so when I was looking at passing environment variables to React today, I happened across this website https://create-react-app.dev/docs/adding-custom-environment-variables/ which says that all enviroment variables used by React have to start with REACT_APP for security reasons.

Proxy in production React for fetch API express

I was developping a app with React app. In developing env i was using proxy but I'm deploying the app and I saw that proxy didn't work in.
I read about http-proxy-middleware. It can be a solution or it don't works too?
Any way to do this without config the server with redirects to other port?
I need to continue fetching to my API server.
The best way what I found without configure server and NGINX is follow this steps:
Build front
Move folder into a backend server.
Put that code after routes:
if (process.env.NODE_ENV === 'production') {
app.use(express.static(`${__dirname}/yourFrontFolder/build`));
app.get('*', (req, res) => {
res.sendFile(`${__dirname}/yourFrontFolder/build/index.html`);
})
...
And build your backend code and access to your backend port like frontend.
You don't usually need a proxy in your React app when it is deployed. To deploy, you usually run npm run build, which creates a build directory containing all the compiled JavaScript and HTML files you need for the deployment. These are then served by a web server, such as NGINX or by your backend application.

Categories

Resources