create-react-app icon indicating copy to clipboard operation
create-react-app copied to clipboard

In CRA 5.0.0, `react-scripts start` fails when both `HOST` in `.env` and `proxy` in `package.json` are defined.

Open BalzGuenat opened this issue 4 years ago • 19 comments

Describe the bug

In CRA 5.0.0, react-scripts start fails when both HOST in .env and proxy in package.json are defined.

Did you try recovering your dependencies?

This occurs on a newly created project.

Which terms did you search for in User Guide?

"allowedHosts" and others, came up empty.

Environment

Environment Info:

  current version of create-react-app: 5.0.0
  running from /home/z003w3we/.npm/_npx/c67e74de0542c87c/node_modules/create-react-app

  System:
    OS: Linux 5.4 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (4) x64 Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz
  Binaries:
    Node: 16.13.0 - ~/.asdf/installs/nodejs/16.13.0/bin/node
    Yarn: 1.22.10 - ~/.asdf/shims/yarn
    npm: 8.1.3 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Chrome: 96.0.4664.45
    Firefox: 95.0
  npmPackages:
    react: ^17.0.2 => 17.0.2 
    react-dom: ^17.0.2 => 17.0.2 
    react-scripts: 5.0.0 => 5.0.0 
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

  1. Create a new app.
  2. Set HOST in .env.
  3. Set proxy in package.json.
  4. Run react-scripts start or something to that effect.

Expected behavior

App starts.

Actual behavior

I get this error:

> yarn start
yarn run v1.22.10
$ react-scripts start
Attempting to bind to HOST environment variable: test.localhost
If this was unintentional, check that you haven't mistakenly set it in your shell.
Learn more here: https://cra.link/advanced-config

Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
 - options.allowedHosts[0] should be a non-empty string.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Reproducible demo

https://github.com/BalzGuenat/cra-test

BalzGuenat avatar Dec 15 '21 12:12 BalzGuenat

I debugged a bit and found that in webpackDevServer.config.js#L46, allowedHosts is set to [undefined] because prepareUrls doesn't set lanUrlForConfig if a host is specified.

BalzGuenat avatar Dec 15 '21 12:12 BalzGuenat

@BalzGuenat I can replicate the issue - did this work in webpack 4 (what version?)

raix avatar Dec 15 '21 23:12 raix

Yeah, it works in webpack 4.44.2.

BalzGuenat avatar Dec 16 '21 09:12 BalzGuenat

The answer from josipat in

https://stackoverflow.com/questions/70374005/invalid-options-object-dev-server-has-been-initialized-using-an-options-object/70491173#70491173

works. I will just paste his answer here again, just for easy access.

  1. Delete "proxy": "http://localhost:xxxx" in package.json
  2. run npm install http-proxy-middleware
  3. Create a file setupProxy.js inside your src folder and write the following codes:
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:6000',
      changeOrigin: true,
    })
  );
};
  1. run npm start

sunmoon-idegu avatar Dec 27 '21 02:12 sunmoon-idegu

@sunmoon-idegu I'm not sure how important it is, but the syntax of the above snippet is a little misleading. I think what the intention was to create a proxy on the /api routes, rather than the / routes. I noticed this because the output of the log was saying:

[HPM] Proxy created: / -> https://localhost:6000

Instead of:

[HPM] Proxy created: /api -> https://localhost:6000

So, to fix this you will notice the path (HPM's context) is not being set, therefore defaulting to /. You can correctly set via:

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

module.exports = function(app) {
  app.use(
    createProxyMiddleware('/api', {
      target: 'http://localhost:6000',
      changeOrigin: true,
    })
  );
};

Also, saving someone a doc lookup, you will likely need secure: false if testing locally and receiving SSL errors.

marr avatar Dec 28 '21 14:12 marr

I encountered the problem when I tried:

HOST=<something>  yarn start

(and I have a proxy: setting in package.json).

I debugged a bit and found that in webpackDevServer.config.js#L46, allowedHosts is set to [undefined] because prepareUrls doesn't set lanUrlForConfig if a host is specified.

By examining the code at that link I discovered the workaround:

HOST=<something>  DANGEROUSLY_DISABLE_HOST_CHECK=true  yarn start

Before you try that you should read the comment following webpackDevServer.config.js#L25 and determine whether that is dangerous for your situation. In my case it's harmless.

hwinkler avatar Dec 28 '21 21:12 hwinkler

@marr

I'm not sure how important it is, but the syntax of the above snippet is a little misleading. I think what the intention was to create a proxy on the /api routes, rather than the / routes.

It is actually important to notice this because this misleading snippet is the one from the documentation.

I made a PR to fix the documentation #12049 and change the example snippet to one that works as intended with v5.0.0.

HugoGEORGET avatar Feb 11 '22 13:02 HugoGEORGET

Dropping this here for others who may have a similar issue:

My routes did not include "/api" in the API calls. Instead, they relied on the proxy in package.json being used in the event of 404's. When using the previously mentioned solution of using http-proxy-middleware, if I set the context to "/", the proxy was used for all routes, including ones meant for the client. Due to the number of API calls in my app, it would be a significant time commitment to change them all to include the "/api"

I tried using ["/**","!/#/"] to exclude hash routes, but for some reason, it looks like the "#/" wasn't getting looked at at all. The requests were still being proxied, and in the express logs, the route was simply "/" rather than "/#/". My guess is that the hash and everything after it are not truly considered part of the route.

The solution to all of this ended up being adding the following to my index.js:

import axios from 'axios';

axios.defaults.baseURL = '/api';

This prepends "/api" to all axios requests, which allows me to use the solution mentioned by marr.

agbrettpittman avatar Apr 20 '22 12:04 agbrettpittman

Glad you found a workaround Brett. Just to clear up why your # issue. Those are client only elements of the URL and do not make it to the server. I forget where I read that but it would explain your observations.

On Wed, Apr 20, 2022 at 8:36 AM Brett Pittman @.***> wrote:

Dropping this here for others who may have a similar issue:

My routes did not include "/api" in the API calls. Instead, they relied on the proxy in package.json being used in the event of 404's. When using the previously mentioned solution of using http-proxy-middleware, if I set the context to "/", the proxy was used for all routes, including ones meant for the client. Due to the number of API calls in my app, it would be a significant time commitment to change them all to include the "/api"

I tried using ["/**","!/#/"] to exclude hash routes, but for some reason, it looks like the "#/" wasn't getting looked at at all. The requests were still being proxied, and in the express logs, the route was simply "/" rather than "/#/". My guess is that the hash and everything after it are not truly considered part of the route.

The solution to all of this ended up being adding the following to my index.js:

import axios from 'axios';

axios.defaults.baseURL = '/api';

This prepends "/api" to all axios requests, which allows me to use the solution mentioned by marr.

— Reply to this email directly, view it on GitHub https://github.com/facebook/create-react-app/issues/11762#issuecomment-1103881634, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAK2WEAZDOJQ22BT2N6EQDVF723TANCNFSM5KDPQPNQ . You are receiving this because you were mentioned.Message ID: @.***>

marr avatar Apr 20 '22 13:04 marr

HOST=<something>  DANGEROUSLY_DISABLE_HOST_CHECK=true  yarn start

I encountered this issue in a project running docker-compose. Testing this^ solution, in docker-compose, produces below results:

DANGEROUSLY_DISABLE_HOST_CHECK HOST Startup result Proxying works?
undefined undefined Fails with error 1 below n/a
true undefined Starts fine. No warnings. No - still troubleshooting
true something Fails with error 2 below n/a
true localhost Starts with warning 1 below, but React server never returns anything to the browser n/a
undefined localhost Warning 1, then Error 1 n/a
undefined something Warning 1, then Error 1 n/a

I suspect my proxying implementation may be bugged, but it's hard to confirm right now.

Error 1

Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
 - options.allowedHosts[0] should be a non-empty string.

Error 2

Error: getaddrinfo ENOTFOUND something
  at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:83:26) {
  errno: -3008,
  code: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'something'
}

Warning 1

Attempting to bind to HOST environment variable: localhost
If this was unintentional, check that you haven't mistakenly set it in your shell.
Learn more here: https://cra.link/advanced-config

daweimau avatar Apr 23 '22 06:04 daweimau

https://github.com/facebook/create-react-app/issues/11762#issuecomment-1001295074

This works in a js project, but for some reason not in a ts project (created with npx create-react-app client --template typescript).

Fortunately creating setupProxy.js, even in a typescript project, will still work (as long as the project allows js)

daweimau avatar Apr 23 '22 09:04 daweimau

I'd same problem but it fixed by setupProxy.js

Navid61 avatar May 07 '22 04:05 Navid61

The stepProxy.js doesn't work for me. reproduce: https://github.com/bradtraversy/mern-tutorial/tree/main/frontend

AliceSum avatar May 12 '22 17:05 AliceSum

The stepProxy.js doesn't work for me. reproduce: https://github.com/bradtraversy/mern-tutorial/tree/main/frontend

This project has no setupProxy.js at all and appears to follow none of the steps described

daweimau avatar May 14 '22 10:05 daweimau

If you have access to server, just install cors from npm. For Express: https://expressjs.com/en/resources/middleware/cors.html

meves avatar May 27 '22 07:05 meves

I have the same problems. For a while it worked with DANGEROUSLY_DISABLE_HOST_CHECK=true but I think an update of express or node (don't remember from which to which version) broke it again.

After spending a couple of hours on it, I settled for a solution with using caddy as a reverse proxy. For anybody looking for a similar solution, here is the snippet from my Caddyfile:

http://localhost:3001 {
  # API Backend is running on port 6000
  reverse_proxy /api/* http://localhost:6000
  reverse_proxy /auth/* http://localhost:6000
  # ... add more API end points if necessary
  reverse_proxy /* http://localhost:3000
}

Then, run npm with

WDS_SOCKET_PORT=3001 npm start

setting also the WS port to make hot reloading work. Then, you can work on localhost:3001.

So far, it seems to work.

bielern avatar Jun 17 '22 10:06 bielern

https://stackoverflow.com/questions/70374005/invalid-options-object-dev-server-has-been-initialized-using-an-options-object/72100528#72100528

This is actually likely caused by the address module if thats a dependency here

salazarm avatar Jun 13 '23 15:06 salazarm

The answer from josipat in

https://stackoverflow.com/questions/70374005/invalid-options-object-dev-server-has-been-initialized-using-an-options-object/70491173#70491173

works. I will just paste his answer here again, just for easy access.

1. Delete "proxy": "http://localhost:xxxx" in package.json

2. run `npm install http-proxy-middleware`

3. Create a file setupProxy.js inside your src folder and write the following codes:
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:6000',
      changeOrigin: true,
    })
  );
};
4. run `npm start`

thank you its working properly

PRASHA02 avatar Dec 30 '23 15:12 PRASHA02

thank you very much for this.

The answer from josipat in

https://stackoverflow.com/questions/70374005/invalid-options-object-dev-server-has-been-initialized-using-an-options-object/70491173#70491173

works. I will just paste his answer here again, just for easy access.

  1. Delete "proxy": "http://localhost:xxxx" in package.json
  2. run npm install http-proxy-middleware
  3. Create a file setupProxy.js inside your src folder and write the following codes:
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:6000',
      changeOrigin: true,
    })
  );
};
  1. run npm start

this helps with my issue

Ny0ttt avatar Mar 22 '24 09:03 Ny0ttt