ryanve
ryanve

Reputation: 52601

How to setup react-router to work on localhost and deployment URL under path

I'm using webpack-dev-server to locally host a repo on localhost:1111. We have setup Jenkins such that pushing to this repo on any branch is viewable on a url like jenkins.example.com/repo/branch/. I'm trying now to setup routing with react-router

import { Router, Route, Link } from "react-router-dom";
import createBrowserHistory from "history/createBrowserHistory";
const history = createBrowserHistory();

and am rendering like

<Router history={history}>
  <div>
    <nav>
      <Link to="/">Home</Link>
      <Link to="/Example">Example</Link>
    </nav>
    <Route exact path="/" render={Home} />
    <Route path="/Example" render={Example} />
  </div>
</Router>

This works on localhost as expected. localhost:1111/Example renders Example. But <Link to="/Example"> links to jenkins.example.com/Example there. Using ./Example does not work at all. How can I setup react-router such that it continues to work locally as localhost:1111/Example but uses a URL like jenkins.example.com/repo/branch/Example instead?

Upvotes: 0

Views: 4548

Answers (1)

GProst
GProst

Reputation: 10237

You can use <Router>'s basename property to solve this problem. So for your Jenkins server you have to define basename = '/repo/branch' and router will work as expected.

But the problem is how you can dynamically set basename for your router. Because today you use Jenkins, tomorrow localhost and the day after tomorrow it is a production server.

For this particular problem you can use custom environment variable (for instance MY_APP_ROUTER_BASENAME) and pass it to the resulting app build via webpack.DefinePlugin as follows:

// in your webpack.config.js

// get basename from your custom environment variable
const routerBasename = process.env.MY_APP_ROUTER_BASENAME

const config = {
  ...
  plugins: [
    ...
    new webpack.DefinePlugin({
      process: {
        env: {
          ROUTER_BASENAME: JSON.stringify(routerBasename)
        }
      }
    }),
    ...
  ],
  ...
}

module.exports = config

And then in your app codebase you can get this variable like this:

// also set default value (for using at localhost for example)
const basename = process.env.ROUTER_BASENAME || '/'

...

<Router history={history} basename={basename}>
  ...
</Router>

Upvotes: 2

Related Questions