Using `"homepage"` in package.json, without messing up paths for localhost
This question actually follows directly from my answer on a previous question.
I added a "homepage"
to my package.json
because it is a React app that I hosted on Github Pages. The output of npm run build
say that the /build
directory can now be deployed, and it assumes the project is being hosted at /project_name/
.
But on localhost, the project is not being hosted at /project_name/
, so the paths being requested for js and css are messed up (looking for /project_name/static/...
instead of /static/...
) and the app broken.
How can one have the homepage field in package.json so that they can deploy to Github Pages (for example) while still develop locally with a working app?
Docs for create-react-app
explains how to serve same build from different relative paths.
If you put homepage as
"homepage": ".",
assets will be served relative to index.html
. You will then be able to move your app from http://mywebsite.com
to http://mywebsite.com/relativepath
or even http://mywebsite.com/relative/path
without having to rebuild it.
For development purposes, serving using yarn start
or npm start
is good enough. App will be available in localhost
You can use PUBLIC_URL
environment variable to override the homepage for a specific build.
Even better have it set in your package.json, for instance:
{
// ...
"scripts": {
"build": "react-scripts build",
"build-localhost": "PUBLIC_URL=/ react-scripts build"
// ...
}
// ...
}
You can override the homepage setting using you dev shell environment:
$ export PUBLIC_URL=http://localhost:3000/
$ yarn start
or if you prefer, remove your homepage setting and configure your env before building for production:
$ export PUBLIC_URL=http://example.com/subdir
$ yarn build
For people coming here looking for an all-in-one answer which also covers react-router-dom:
-
Add
package.json['homepage']
to be your production url. To be noted, the CRA build step removes the domain part of the url to leave only the path to index. -
When building for localhost, do
PUBLIC_URL=/ npm run build
-
Add
<base href="%PUBLIC_URL%" />
in yourpublic/index.html
page as proposed in this article ; it will provide support for assets (img, css) and will expose the%PUBLIC_URL%
to be reused later. -
In the component which creates your BrowserRouter (typically App.js or main.js), add:
const basename = document.querySelector('base')?.getAttribute('href') ?? '/'
-
use as:
<BrowserRouter basename={basename} />