5

I created a react app that will be served from /example-path. I defined it in the package.json like this:

"homepage":"/example-path"

It has worked so far, but now I would like to add routing with react-router-dom, and it incorrectly detects /example-path as the part of the URL.

This is my code:

<Router>
  <Switch>
    <Route path="/product/:id" children={<DisplayProduct />} />
  </Switch>
</Router>

Unfortunately react-router-dom tries to match the full URL /example-path/product/10. How is it possible to avoid that? Is it possible to access the homepage variable somehow?


I could use <Router basename="/example-path">, but in that way, this parameter is a duplicate. I would like to define it in only one place.

Federico Navarrete
  • 3,069
  • 5
  • 41
  • 76
Iter Ator
  • 8,226
  • 20
  • 73
  • 164
  • you don't need to access Package.json to read which is your homepage route. You want to add a concern to Package.json that does not belong to it. You can use a config.js with this configurable args and read it wherever you like. – JoelBonetR Jul 26 '21 at 12:41
  • @JoelBonetR In a react project, the project root path has do be defined in the homepage parameter of package.json. That's not my choise – Iter Ator Jul 26 '21 at 13:02
  • hmm no, why you should add the project root path in the package.json? You only have the entry point of your app in your package.json if you had set scripts to simplify the running, such "parcel index.js" or similar – JoelBonetR Jul 26 '21 at 13:06
  • @JoelBonetR Otherwise if I put my app to `/example-path/...` the app tries to load assets from `/static/` instead of `/example-path/static/...` – Iter Ator Jul 26 '21 at 13:10
  • so you linked/required resources on a bad manner and now you want to add the full path instead... example-path must be the root path of your application, so when you link an asset you must use relative path './static/asset'. *Note the dot before the slash – JoelBonetR Jul 26 '21 at 13:12
  • @JoelBonetR No, I created the app with `npx create-react-app`. I did not add additional assets to it – Iter Ator Jul 26 '21 at 14:16
  • can you provide a pic of your project's structure and the package.json code? – JoelBonetR Jul 26 '21 at 14:20
  • Do you have access to your bundler config ? (webpack, ...) – hjrshng Aug 02 '21 at 10:01

5 Answers5

7

How is it possible to access homepage from package.json in a react app?

We can access the URL set in package.json's homepage field using PUBLIC_URL environment variable.

We sometimes use a relative URL to deploy the application in subdirectories for example we are deploying the application in https://myhostname.com/example-path.

In order to do that, we can either set the environment variable PUBLIC_URL=/example-path for the application build or set the package.json homepage attribute to "/example-path". In your case, you have set the

"homepage": '/example-path/'

then the PUBLIC_URL would be set to /example-path/. Now you can access this environment variable anywhere in your react application.

<Router basename={process.env.PUBLIC_URL}>
  <Switch>
    <Route path="/product/:id" children={<DisplayProduct />} />
  </Switch>
</Router>

After running the npm run build, you can check in the build/index.html that all the places where you used the %PUBLIC_URL% is set to /example-path/ like below;

<script type="text/javascript" src="/example-path/static/js/main.ec7f1972.js">
Subrato Pattanaik
  • 5,331
  • 6
  • 21
  • 52
3

The Router doesn't know anything about your package.json. It just looks at the browser location. You can set a basename if you use BrowserRouter:

import {BrowserRouter as Router} from 'react-router';
<Router basename="/example-path">
    {/* ... */}
</Router>
trixn
  • 15,761
  • 2
  • 38
  • 55
  • 1
    @IterAtor The `package.json` is not meant to be read by your app code, but by a package manager. You could maybe build a tool that reads it and makes it available as built-time variables in your javascript modules but why all that efford? I don't know of any available tool that does this. But you would still have to provide that as a `basename` to the `Router`. As the `basename` will likely not change often, this is pretty much wasted time. – trixn Feb 26 '21 at 11:01
3

Edit: With the addition of environment variables to react-scripts@0.2.3 and higher prefer @Alan Omars answer: Prefix an environment variable with REACT_APP_ and it will be exposed to the client at build time. docs

Here's the old answer that uses the fact that Webpack blindly replaces %PUBLIC_URL%in index.html:

Assuming you are using create-react-app, this is actually pretty straightforward:

Add the following to public/index.html:

<script>
  window.PUBLIC_URL = "%PUBLIC_URL%";
</script>

now you can reference the homepage from JavaScript! Simply access it via

const myPublicUrl = window.PUBLIC_URL;

Note: The variable will be an empty string if no homePage field is set in the package.json, so we have to compensate for that:

<Router basename={window.PUBLIC_URL && window.PUBLIC_URL.length > 0 ? window.PUBLIC_URL : "/"}>
    {/* ... */}
</Router>
Taxel
  • 3,859
  • 1
  • 18
  • 40
2

Since you are using create-react-app package you can use environment variable instead of "homepage":"/example-path" in your package.json:

  1. create .env file in the root of your project.

  2. add REACT_APP_HOME_PAGE='/example-path/' to the .env file

  3. now you can access your env variable through process.env.REACT_APP_HOME_PAGE in your app like the following:

    <Router basename={process.env.REACT_APP_HOME_PAGE}>
    
Alan Omar
  • 4,023
  • 1
  • 9
  • 20
0

I don't know where is the location of your Router file but you can try to import it as json in src/index.js file that created by create-react-app cli app like below;

import myPackageJson from '../package.json';

or

import { homepage } from '../package.json';
Serhan C.
  • 1,152
  • 1
  • 12
  • 10