Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject port and host using ENV variable in Create React App Proxy settings?

Is it possible to set proxy settings in CRA differently than with package.json? For example using ENV variables?

From CRA docs it states

Use environment variables to inject the right server host and port into your app.

Is this sentence about proxy or dev server itself?

According to the this and this, the only way to influence proxy settings is via package.json.

like image 522
Tom Witek Avatar asked Oct 11 '17 10:10

Tom Witek


People also ask

How do I change the port in Create React app?

To change the default port for a create-react-app project, update the start command in your package. json file to specify the port, e.g. "PORT=3456 react-scripts start" on macOS and Linux and "set PORT=3456 && react-scripts start" on Windows.

How do I use a proxy server in React?

Proxy Setup with Create-React-App All you have to do is add a proxy field to your package. json file, like shown below. "proxy": "http://localhost:3000", This line instructs the development server to proxy any unknown requests to your API server in development mode.


2 Answers

Note: this feature is available with [email protected] and higher.

You can manually configure proxy now. You need to install http-proxy-middleware first.

npm install http-proxy-middleware --save

Then create a file src/setupProxy.js with following content.

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api', // You can pass in an array too eg. ['/api', '/another/path']
    createProxyMiddleware({
      target: process.env.REACT_APP_PROXY_HOST,
      changeOrigin: true,
    })
  );
};

You can add proxy now in the .env file, remember you need the REACT_APP_ prefix for development server to pick up the environment variable.

REACT_APP_PROXY_HOST=http://localhost:5000

Ref: Proxy manually

like image 139
MjZac Avatar answered Sep 19 '22 15:09

MjZac


Regarding:

Use environment variables to inject the right server host and port into your app.

This refers to neither the proxy server nor the dev server. This is a recommendation on how to handle per-environment server settings if proxy does not provide enough flexibility for you (i.e. if you need to use protocols other than http, https, or ws). For example, if you have an api call within your code, you can use an environment variable to do something like this:

axios(process.env.REACT_APP_BASE_URL + endpoint, options).then(data=>{ console.dir(data); })

Where each environment has it's own definition of REACT_APP_BASE_URL.


Without package.json:

It is not possible to influence proxy settings without modifying package.json.

See Configuring the Proxy Manually (CRA docs)

package.json is the only documented way to influence proxy settings.

You can also see line 96 of CRA's start.js. This implementation leaves absolutely no ability to use ENV vars to inject the host/port to CRA's proxy settings.

This is really one of the reasons I detest CRA, to be honest. All of this behavior is so very easily handled when not bound by the limitations of CRA.


You could just eject create react app:

npm run eject

All of these problems will go away instantly... The start.js script referenced above is a bit of the code that is ejected. So you would very easily be able to replace those proxy settings with ENV vars.

Just be certain to create a checkpoint for yourself prior to doing this as there is no reverting an ejection.

However--if you must stick with CRA--you CAN very easily modify package.json using environment variables.


How to inject ENV vars into package.json at build time:

This is essentially what CRA does with the REACT_APP_ env vars (though it directly injects them into process.env).

package.json is just a big JSON object, so all you need to do is parse it on the server side right before you deploy, update the "proxy" value to the ones provided by your ENV vars, save the file, and then run your build/deploy.

Here is a very simple example of how to achieve this, you just need to run this script before deployment in a context where you still have access to process.env:

const fs = require('fs');

// read/process package.json
const file = './package.json';
let pkg = JSON.parse(fs.readFileSync(file).toString());

// at this point you should have access to your ENV vars
pkg.proxy = `${process.env.HOST}:${process.env.PORT}`;

// the 2 enables pretty-printing and defines the number of spaces to use
fs.writeFileSync(pkg, JSON.stringify(file, null, 2));

I know this doesn't explicitly answer the question of how to handle this "without package.json", but I don't think that's the necessary approach anyways.

Further, this DOES asnswer the title question of "How to inject port and host using ENV variable in Create React App Proxy settings?"

like image 20
Jonny Asmar Avatar answered Sep 22 '22 15:09

Jonny Asmar