Can't build create-react-app project with custom PUBLIC_URL

I'm trying

PUBLIC_URL=http://example.com npm run build

with a project built using the latest create-react-script.

However, the occurrences of %PUBLIC_URL% in public/index.html are replaced with an empty string, not the expected value PUBLIC_URL.

public/index.html contains code like

<script src="%PUBLIC_URL%/static/js/jarvis.widget.min.js"></script>

Hours of searching the internet and stack overflow show that very little is written about PUBLIC_URL. I cloned create-react-app from GitHub and have been browsing the code but have not yet been enlightened.

Does anyone have any suggestions as to what I'm doing wrong?


Solution 1:

If the other answers aren't working for you, there's also a homepage field in package.json. After running npm run build you should get a message like the following:

The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:

  "homepage" : "http://myname.github.io/myapp",

You would just add it as one of the root fields in package.json, e.g.

{
  // ...
  "scripts": {
    // ...
  },
  "homepage": "https://example.com"
}

When it's successfully set, either via homepage or PUBLIC_URL, you should instead get a message like this:

The project was built assuming it is hosted at https://example.com.
You can control this with the homepage field in your package.json.

Solution 2:

People like me who are looking for something like this in in build:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

Then setting https://dsomething.cloudfront.net to homepage in package.json will not work.

1. Quick Solution

Build your project like this:
(windows)

set PUBLIC_URL=https://dsomething.cloudfront.net&&npm run build

(linux/mac)

PUBLIC_URL=https://dsomething.cloudfront.net npm run build

And you will get

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

in your built index.html

2. Permanent & Recommended Solution

Create a file called .env at your project root(same place where package.json is located).
In this file write this(no quotes around the url):

PUBLIC_URL=https://dsomething.cloudfront.net

Build your project as usual (npm run build)
This will also generate index.html with:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

3. Weird Solution (Will do not work in latest react-scripts version)

Add this in your package.json
"homepage": "http://://dsomething.cloudfront.net",

Then index.html will be generated with:

<script type="text/javascript" src="//dsomething.cloudfront.net/static/js/main.ec7f8972.js">

Which is basically the same as:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

in my understanding.

Github Issue Github Comment

Solution 3:

That is not how the PUBLIC_URL variable is used. According to the documentation, you can use the PUBLIC_URL in your HTML:

<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

Or in your JavaScript:

render() {
  // Note: this is an escape hatch and should be used sparingly!
  // Normally we recommend using `import` for getting asset URLs
  // as described in “Adding Images and Fonts” above this section.
  return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}

The PUBLIC_URL is not something you set to a value of your choosing, it is a way to store files in your deployment outside of Webpack's build system.

To view this, run your CRA app and add this to the src/index.js file:

console.log('public url: ', process.env.PUBLIC_URL)

You'll see the URL already exists.

Read more in the CRA docs.

Solution 4:

Actually the way of setting environment variables is different between different Operating System.

Windows (cmd.exe)

set PUBLIC_URL=http://xxxx.com&&npm start

(Note: the lack of whitespace is intentional.)

Linux, macOS (Bash)

 PUBLIC_URL=http://xxxx.com npm start

Recommended: cross-env

{
  "scripts": {
    "serve": "cross-env PUBLIC_URL=http://xxxx.com npm start"
  }
}

ref: create-react-app/README.md#adding-temporary-environment-variables-in-your-shell at master · facebookincubator/create-react-app

Solution 5:

Have a look at the documentation. You can have a .env file which picks up the PUBLIC_URL

Although you should remember that what its used for -

You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application.