23

I'm building a site using react and react-router. My site is split into two sections: front and partners section. I want the partners section to be accessed using a subdomain partner. I have written the following code since react-router does not support subdomain routing. I'm unsure whether or not this is 'good practice'. So my question is, is this a proper solution, if not, what are the alternatives?

<BrowserRouter>
  <Route path="/" render={props => {
    const [subdomain] = window.location.hostname.split('.');
    if (subdomain === 'partner') return <PartnerLayout {...props}/>;
    return <AppLayout {...props}/>;
  }}/>
</BrowserRouter>
Rasmus Nørskov
  • 478
  • 1
  • 6
  • 20
  • 20
    react-router is just a client side library. subdomain routing is something handled at the server level (nginx / node etc). So if you want to reuse the same code and have different components based on the url then what you're doing is fine. – azium Jul 13 '17 at 20:31
  • 3
    The alternative would be to provide a second entry point that has it's own top level component. So you basically have two different components that you bundle into two different js files and serve them on the correct subdomain. Depending your app on the domain is definitely an anti-pattern. What if you want to deploy to a test system with an unexpected domain. You would be forced to adapt your code. Webpack can bundle common dependencies into an own file so you don't have to serve all your js twice (for browser caching). – trixn Jul 13 '17 at 20:43
  • Thanks this is great solution. Just a little addition so that it works with two part TLDs and also to check if it is a subdomain at all: ` { const subdomain = window.location.hostname.split('.'); if (subdomain && subdomain.length > 1) return ; return ; }}/> ` – semyd Feb 07 '19 at 15:55
  • Careful if you are rendering this on the server (your app is SSR) then that window will throw an Undefined error hence the server does not know a variable called window so If I were you I would wrap the whole thing in `if(typeof window !== "undefined")` – Nader Zouaoui Feb 22 '20 at 13:00
  • A better way would be to serve the app from two different starting points (where you call ReactDOM.render or hydrate) and each one would serve a different router. What are you using to serve the app? if a small node server than it shouldn't be more than a couple of minutes to set it up. – Nader Zouaoui Feb 22 '20 at 13:05

2 Answers2

2

I don't use react-router, but the following should work if you just add react router jsx to the individual application components

import React from 'react';

import {MainApplication} from './Main';

function subdomainApplications (map) {
  let main = map.find((item)=> item.main);
  if (!main) {
    throw new Error('Must set main flag to true on at least one subdomain app');
  }

  return function getComponent () {
    const parts = window.location.hostname.split('.');

    let last_index = -2;
    const last = parts[parts.length - 1];
    const is_localhost = last === 'localhost';
    if (is_localhost) {
      last_index = -1;
    }

    const subdomain = parts.slice(0, last_index).join('.');

    if (!subdomain) {
      return main.application;
    }

    const app = map.find(({subdomains})=> subdomains.includes(subdomain));
    if (app) {
      return app.application;
    } else {
      return main.application;
    }
  }
}

const getApp = subdomainApplications([
  {
    subdomains: ['www'],
    application: function () {
      return 'Main!'
    }
    main: true
  },
  {
    subdomains: ['foo'],
    application: function () {
      return 'Foo!';
    }
  },
  {
    subdomains: ['bar', 'baz.bar'],
    application: function () {
      return 'Bar!';
    }
  }
]);

export default function Application () {
  const App = getApp();
  return (
    <App className="Application" />
  );
}
Stephen Handley
  • 2,325
  • 3
  • 19
  • 17
-2

It's a good practice to treat primary domain code and sub domain code as different codebases. Also as you are aware and react-router is a client side module. Although this hack might work, it's generally frowned upon.

Prashanth M
  • 326
  • 1
  • 7
  • 12
    Totally disagree. No reason a single SPA shouldn't work across multiple subdomains and there are often situations where that's required, for example vanity subdomains ie. *.tumblr.com – Stephen Handley Jun 18 '20 at 21:54