Configuring app's basename in react-router

回眸只為那壹抹淺笑 提交于 2019-12-06 08:33:27

问题


I'm struggling a bit with react-router 2.x configuration, specifically app basename.

I've an application which may have different base root throughout its lifecycle. For instance:

  • / in development
  • /users in production
  • /account in production after migration

The basename comes into play in several places:

  • static asset compilation in Webpack
  • react-router main configuration
  • specifying redirect routes in redux actions
  • providing something like redirectUrl to API calls

My current solution is to have an ENV variable and make it available both to Webpack and to the app itself by injecting window.defs via an Express server, but I still end up having things like ${defs.APP_BASENAME}/signin in way too many places throughout the app.

How can I abstract the app base, or at least tuck it away in a single location? I should be able to specify the base route in Router's config, and then simply use relative routes somehow, right? Or am I missing something?


回答1:


You can decorate your history with a basename. You could mix this with a DefinePlugin in your Webpack configuration to specify which basename should be used.

// webpack.config.js
new Webpack.DefinePlugin({
  BASENAME: '/users'
})

// somewhere in your application
import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'

const history = useRouterHistory(createHistory)({
  basename: BASENAME
})

Given the basename: /users, React Router will ignore the /users at the beginning of the pathname so:

  1. The URL /users is internally matched by the path /

  2. The URL /users/profile matches the path /profile.

Similarly, you do not have to append the basename to the path when you are navigating within your application.

  1. <Link to='/friends'>Friends</Link> will navigate to /friends internally, but the URL in the location bar will be /users/friends.



回答2:


Today I ran into the same issue: On my localhost I let an NGINX serve the stuff in the root context, but on my prod server, an Apache serves the stuff from a subdirectory...

Inspired by the answer from Paul S and inspired by the infos here: https://github.com/ReactTraining/react-router/issues/353

I got the for me working solution:

In the Webpack config file I defined a plugin for my localhost dev env:

  plugins: [
    new webpack.DefinePlugin({
      BASENAME: JSON.stringify("/")
    })
  ],

In the Webpack PROD config file I defined a plugin for my prod env in a subfolder, i.e. www.example.com/users:

  plugins: [
    new webpack.DefinePlugin({
      BASENAME: JSON.stringify("/users/")
    }),

And in my react-router definitions I just reference:

import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { useBasename } from 'history'
...
<Router history={useBasename(() => browserHistory)({ basename: BASENAME })}>

For me a very elegant solution and easy too. It just cost me around five hours of looking around :-)



来源:https://stackoverflow.com/questions/41440240/configuring-apps-basename-in-react-router

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!