Usage in apps spanning multiple origins/domains
See original GitHub issueI’m trying to integrate redux-first-router into a site which has multiple domains, and there are some sticking points in my mind relating to these domains. I’m curious if you can see a better solution to what I’ve got, or if you think it would be worth extending the API to support this use case.
The situation
- There is one main domain at
website.com
- There are many custom domains at
client1.com
,client2.com
, etc - Some pages can appear on both domains, e.g.
client1.com/settings
andwebsite.com/settings
both work - Some other pages can appear at different paths on the main domain vs the client domain if it exists, e.g.
client1.com/pages/somepage
is the same type of page aswebsite.com/client2/pages/somepage
(client1 has a custom domain but client2 does not). - I realise this setup is not optimal, but changing it is impractical.
Intended outcome
- When we write components that have links or can do navigation, we dispatch routing actions or use
redux-first-router-link
. - We reuse the same components everywhere without regard to which domain they will be rendered on, and the links still work.
- When a user clicks on a link for a routing action which is available on the domain they are currently on, an SPA transition occurs.
- When a user clicks on a link for a routing action which is not available on the domain they are currently on, it acts like a link and takes them to the correct page on the other domain, reloading the page on the way (because same origin policy)
Currenty imagined solution
const routesMap = {
MARKETING: {
origins: ['https://website.com'],
path: '/marketing',
},
USER_SETTINGS: {
path: '/settings',
origins: ['https://website.com', 'https://(?<clientDomain>.*)'],
stickyOrigin: true, // Stay on the current domain if possible, even if it isn't first in the list
},
CLIENT_PAGE: {
origins: {
'https://(?<clientDomain>.*)': {
path: '/pages/:pageName',
isAllowed: (getState, action) => !!getState().clients[action.payload.clientPrefix].domain,
},
'https://website.com': {
path: '/:clientPrefix/pages/:pageName',
isAllowed: (state, action) => !state.clients[action.payload.clientPrefix].domain,
},
},
},
};
dispatch({ type: MARKETING, })
would always go to website.com/marketing
, doing an SPA transition if the current origin was already website.com
.
dispatch({ type: USER_SETTINGS, })
would always transition to /settings
on the current origin
dispatch({
type: CLIENT_PAGE,
payload: {
clientPrefix: 'client1',
clientDomain: 'https://client1.com',
pageName: 'apples',
},
})
would SPA transition from anywhere on client1.com
to client1.com/pages/apples
, and cause a reload from any other domain
dispatch({
type: CLIENT_PAGE,
payload: {
clientPrefix: 'client2',
clientDomain: null,
pageName: 'oranges',
},
})
would SPA transition from anywhere on website.com
to website.com/client2/pages/oranges
, and cause a reload from any other domain
The rest seems difficult to implement without adding to the API of redux-first-router. I’m imagining something like this:
- When matching actions and urls, the usual rules are followed unless a
origins
property is set on the route. If so, the following is done in order:- If
stickyOrigin
is set on the route, use the first origin which the current origin matches. Over time, the app can migrate to using this option and not switching domains on internal links. - Use the first origin who’s regex matches the current browser origin and where
isAllowed
is not set or true orisAllowed(state, action)
returns true - Otherwise return undefined or crash.
- If
- Since
actionToPath
andpathToAction
don’t include an origin, we needactionToUrl
andurlToAction
. These would be similar except that they would return/receive full urls. actionToPath
would at least have to check that the chosen origin for an action is the same as the current option, perhaps returnundefined
otherwise.pathToAction
would need to take into account the current origin when matching the path onroutesMap
- When an action is dispatched that would result in changing the origin, the page should be reloaded at the new origin
redux-first-router-link
would work similarly, especially the<a />
tag’s href would include the domain when necessary.
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (4 by maintainers)
Top GitHub Comments
In case anyone else is interested in doing something like this, I tried it and it works.
The Wrapped
<Link />
component looks something like this:Passing in
getState
to the component is probably not ideal, at some point I’ll try and switch it to a thunk that can be dispatched, but the idea is there.that works. in the next version of Rudy, the action will have the destination path, so you won’t have to do
actionToPath
. But yea,onBeforeChange
is an even better place to do this.