React setupProxy.js for different environments - reactjs

I am very new to react but my issue is really around strategies for deploying my app to different environments (dev, QA, UAT). My react app makes an api call and I am using a setupProxy.js to define the url for that api, works great locally. I have also built the api and it is hosted separately. My question is how do I change the setupProxy.js so that the url respects the environment it's deployed to. Right now I'm using AzureDevops and Octopus for building and deploying. It seems like everything gets compiled so trying to change this file after is built won't work. Just looking to see what your deployment strategies are.
Here is my setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
const baseUri = 'http://localhost:5000/api';
const proxy = {
target: baseUri + '/UsageRequest/ScreenScrapeErrors',
changeOrigin: true
}
const proxy2 = {
target: 'https://www.stackoverflow.com',
changeOrigin: true,
}
module.exports = function (app) {
app.use(
'/SceenScrapeErrors',
createProxyMiddleware(proxy)
);
app.use(
'/jobs',
createProxyMiddleware(proxy2)
);
};
I would like to modify the baseUri variable as it's getting deployed to the different environments.

This blog post may help you: https://octopus.com/blog/javascript-configuration
You can move your environmental configuration to a JSON configuration file and modify your app to read the values from that value.
Octopus can replace variables in JSON configuration files during deployment using the structured configuration variables feature.

Related

Transitioning react app from dev to production environment causes 401/unauthorized errors

I've been tasked with transitioning a development CRA build to work in production. Currently we use an api proxy in development with a setupProxy.js file as such:
const BACKEND_URL = process.env.BACKEND_URL
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function setupProxy(app) {
app.use(
'/api',
createProxyMiddleware({
target: BACKEND_URL,
changeOrigin: true,
})
)
}
This works as expected in development but this feature isn't meant for production, so I've changed all the API endpoints to make proper use of the backend url (basically going from axios.get(/api/endpoint) to something like axios.get(`${process.env.BACKEND_URL}/api/endpoint`)
From what I can tell now, the calls are pointed at the right place now (before it was erroring out the whole app), but I immediately get a 401/unauthorized error for every call and even my websockets as soon as I log into the app, no data being returned.
Is there a critical part of the transition to prod - and specifically the replacement of the api proxy - that I am missing? It seems like there some sort of token missing that is causing all my calls to fail but there was no such token as part of the setupProxy file? Any direction or help would be appreciated

Why do we need proxy in create react app?

In some of projects I encountered in create-react-app people use file setuProxy.js which has content like this inside:
const proxy = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
proxy("/api/mobile-activity/ws", {
target: "http://localhost:3001/socket.io",
pathRewrite: { "^/api/mobile-activity/ws": "" },
ws: true,
})
);
app.use(
proxy("/api/vehicle-accident-protocols", {
target: "http://10.1.1.24:7071",
pathRewrite: { "^/api/vehicle-accident-protocols": "" },
})
);
};
I have tried reading about why we need this but most explanations I find online are about how to do this, rarely they explain clearly why we need this. Can someone in easily understandable way explain why we need this file? I am beginner as far as network infrastructure etc is concerned, that's why maybe I am failing to grasp why we need it.
In general, A proxy or proxy server serves as a gateway between your app and the internet. It’s an intermediate server between client and servers by forwarding client requests to resources.
In React, we often use this proxying in the development environment. React uses a create-react-app (webpack dev server) to serve the app in development mode.
Follow this link for more explanations

Firebase - How to create proxy for web app to prevent CORS

I have a React app that pulling data via Rest API from a different domain.
In my development env in order to work around this, I am using http-proxy-middleware.
module.exports = function (app) {
app.use(
createProxyMiddleware("/shabbat", {
target: "https://www.hebcal.com",
changeOrigin: true
})
)
}
Since I am using Firebase to host my web app I need to handle this via Firebase but can't figure it our how to properly configure.
I would appreciate it if someone can share a working example.
Thank you
i also got this error, i changed to use another https://xxx api to test,then worked well, so i guess this issue is due to firebase's settings, but i haven't found the solution

what is the proper way to do config lookups in react?

My React app currently uses my local API when making an axios.get() call with the following url:
http://localhost:3000/users
Instead of hard-coding the url, I need my component to do a lookup against the config file that is currently configured for the current environment. For example, when my API is running on Azure the axios get call should use the following url:
https://my-api.azurewebsites.net/users
What is the proper way to lookup this config value in a React app? For example, should I create some type of config.js file? What is the proper import/code for my component to hook into the config file for lookup?
Don't use dotenv, because this package was designed for server-side app - it injects config variables in the process.env dictionary, but the process global variable only exists in Node apps and is not available in the browser.
There are many other ways to do what you want, perhaps the simplest I can think of is to have a config file that exports values, and the values it exports depends on the environment the scripts runs in:
// config.js
const isProd = location.host === 'my-app.azurewebsites.net'; // or any other check
const devConfig = {
axiosBaseUrl = 'http://localhost:3000'
}
const prodConfig = {
axiosBaseUrl = 'https://my-app.azurewebsites.net'
}
export default isProd ? prodConfig : devConfig
// upon starting your app, before making any axios call
import config from './config';
const http = axios.create({
baseUrl: config.axiosBaseUrl
});
// use as such
http.get('/hello-world');
// locally: makes a call to http://localhost:3000/hello-world
// in production: makes a call to https://my-app.azurewebsites.net/hello-world
You can also have a config file which contents depends on the build environment, but that would be more complex to setup and is highly dependent on your build pipeline and there's no details about it in your question.
You can create a config file or can use environment variables.
For environment variables:
Create .env file in the root directory of your project.
Save your URL as REACT_APP_BASE_URL=http://localhost:3000/
Now you can access your base URL when you are making axios requests like this:
process.env.REACT_APP_BASE_URL

How to parameterize variables in a React Webpack app for different environments?

I'm working on a React web app which was created by create-react-app and I am getting ready to deploy it.
The issue is, for development, the app uses the api instance running on my dev environment (localhost:{api-port}) but for the deployed app this should point to the server api instance (api.myapp.com).
Currently the host is just a variable in my networking component:
const hostname = 'localhost:9876'
I plan on using webpack to generate the static files which will be served by the production front-end, and I would like to continue developing using npm start as set up by create-react-app.
What would be the correct way to set up my project such that the host can be set automatically to the correct value based on whether I'm running the dev server or building for production?
A common solution is to check against process.env.NODE_ENV like this:
const hostname = process.env.NODE_ENV === "development" ? "localhost:9876" : "localhost:6789";
You may need to force the environment variable to be present in your Webpack configuration file using the DefinePlugin like this:
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV:JSON.stringify(process.env.NODE_ENV || "development")
}
})
]
An alternative solution might be to use the config package and provide your hostname string as a configuration parameter. config will inherit configurations from files based on the current NODE_ENV. It will start by using configuration from a default.json file, then override it with a development.json, or production.json, depending on your environment.
Note that you'll need for the config files to be copied to your output directory using CopyWebpackPlugin for it to work.
There are definitely many ways you could achieve that. One of those solutions would be to use webpacks's DefinePlugin. In your plugins section in webpack configuration you would add something like this:
new webpack.DefinePlugin({
API_HOST: process.env.NODE_ENV === 'production'
? JSON.stringify('localhost:8080')
: JSON.stringify('api.com')
}),
That creates a global variable API_HOST available everywhere in your codebase, which you can use. You can read more about the DefinePlugin here https://webpack.js.org/plugins/define-plugin/
you could use a relative path when you make any request to your api server instead of calling the full url for your app.
and for your development you could add a proxy property to your package.json file:
{
...
"proxy": {
"/api/*": {
"target" :"http://localhost:9876"
}
}
}
so whenever you make any request that prefixed with /api will be redirected to http://localhost:9876/api this is just in the development but in the production if you make a request prefixed with /api it won't be redirected it will be served normally because the proxy is just available in the dev server coming with create-react-app.

Resources