React-router 子域名路由

23

我正在使用React和React-Router构建网站。 我的网站分为两个部分:前端和合作伙伴部分。 我想使用子域名partner访问合作伙伴部分。 由于React-Router不支持子域名路由,因此我编写了以下代码。 我不确定这是否是“良好的实践”。 因此我的问题是,这是一个适当的解决方案吗? 如果不是,有哪些替代方案?

<BrowserRouter>
  <Route path="/" render={props => {
    const [subdomain] = window.location.hostname.split('.');
    if (subdomain === 'partner') return <PartnerLayout {...props}/>;
    return <AppLayout {...props}/>;
  }}/>
</BrowserRouter>

20
react-router 只是一个客户端库。子域名路由处理是在服务器级别上处理的(nginx / node 等)。如果您想重用相同的代码,并根据 URL 使用不同的组件,则您正在做正确的事情。 - azium
3
另一种选择是提供第二个入口点,该入口点具有其自己的顶级组件。因此,您基本上有两个不同的组件,将它们捆绑到两个不同的js文件中,并在正确的子域上提供它们。依赖于域名的应用程序绝对是一种反模式。如果您想要部署到具有意外域的测试系统,您将被迫调整代码。Webpack 可以将通用依赖项捆绑到自己的文件中,因此您不必将所有js都提供两次(用于浏览器缓存)。 - trixn
谢谢,这是一个很好的解决方案。只需稍作修改,使其适用于两部分顶级域名,并检查它是否为子域名:<BrowserRouter> <Route path="/" render={props => { const subdomain = window.location.hostname.split('.'); if (subdomain && subdomain.length > 1) return <PartnerLayout {...props} subdomain={subdomain[0]}/>; return <AppLayout {...props}/>; }}/> </BrowserRouter> - semyd
如果你正在服务器上渲染此内容(即你的应用程序是SSR),那么该窗口将抛出一个未定义错误,因此服务器不知道名为window的变量。所以如果我是你,我会将整个内容包装在if(typeof window !== "undefined")中。 - Nader Zouaoui
更好的方法是从两个不同的起始点(即您调用ReactDOM.render或hydrate的位置)提供应用程序,并且每个起始点都将提供不同的路由器。您使用什么来提供应用程序?如果是一个小型的Node服务器,那么设置它不应该超过几分钟。 - Nader Zouaoui
2个回答

2

我不使用react-router,但是如果你只需将react router jsx添加到各个应用程序组件中,以下内容应该可以正常工作。

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" />
  );
}

-2

将主域代码和子域代码视为不同的代码库是一个好习惯。同时,您应该知道react-router是一个客户端模块。虽然这种方法可能有效,但通常被认为是不好的做法。


12
完全不同意。一个单一的SPA可以跨多个子域名运行,而且通常情况下这是必要的,比如虚荣子域名,例如*.tumblr.com。 - Stephen Handley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接