Я создаю микро-интерфейсы с помощью React и Vite. У меня возникли проблемы с прохождением нужных мне маршрутов.
'/'
домашняя страница хост-приложения
'/some-tenant'
TenantPage удаленного приложения
'/some-tenant/some-subscription'
Страница подписки на удаленное приложение
При запуске хост-приложения, которое я перехожу к "/some-tenant", ничего не появляется. Когда я перехожу к "/some-tenant/some-sub", TenantPage загружается. "/tenant/sub/test" загружает SubscriptionPage.
Я попробовал несколько вещей, чтобы заставить его работать, но сложная часть заключается в том, что я хочу использовать одни и те же маршруты при независимом запуске удаленного приложения. Есть идеи, как добиться того и другого? Вот репозиторий для воссоздания проблемы. https://github.com/lestersconyers/react-routes/
Фрагменты для справки
хост-приложение App.tsx
const RemoteRootApp = lazy(() => import('remoteApp/RemoteRootApp') as any);
function App() {
return (
<div className = "app">
<React.Suspense fallback = "Loading">
<Routes>
<Route path = "/" element = {<HomePage />} />
<Route path = ":tenant" element = {<RemoteRootApp />} />
<Route path = ":tenant/*" element = {<RemoteRootApp />} />
</Routes>
</React.Suspense>
</div>
)
}
удаленное приложение App.tsx
function App() {
return (
<div className = "app">
<Routes>
<Route path = ":tenant" element = {<TenantPage />} />
<Route path = ":tenant/:subscription" element = {<SubscriptionPage />} />
<Route
path = ":tenant/:subscription/manage"
element = {<ManageSubscriptionPage />}
/>
</Routes>
</div>
)
}
удаленное приложение main.tsx
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
)





Если «удаленное приложение» отображается на пути маршрута "/:tenant/*" «основного приложения», то все его подмаршруты будут построены относительно этого родительского пути маршрута. Проблема в том, что «удаленное приложение» имеет дополнительный «перекрывающийся»/«дублирующий» сегмент пути «арендатора», который смешивает то, что вы ожидаете сопоставить.
Что у вас есть прямо сейчас, с отмеченными совпадающими маршрутами:
хост-приложение App.tsx
const RemoteRootApp = lazy(() => import('remoteApp/RemoteRootApp') as any);
function App() {
return (
<div className = "app">
<React.Suspense fallback = "Loading">
<Routes>
<Route path = "/" element = {<HomePage />} />
{/* Matches
* - "/some-tenant/some-sub"
* - "/tenant/sub/test"
* - "/some-tenant"
*/}
<Route path = "/:tenant/*" element = {<RemoteRootApp />} />
</Routes>
</React.Suspense>
</div>
);
}
удаленное приложение App.tsx
function App() {
return (
<div className = "app">
<Routes>
{/* Nothing matches "/some-tenant" */}
<Route
// "/:tenant/:tenant" matches "/some-tenant/some-sub"
path = ":tenant"
element = {<TenantPage />}
/>
<Route
// "/:tenant/:tenant/:subscription" matches "/tenant/sub/test"
path = ":tenant/:subscription"
element = {<SubscriptionPage />}
/>
<Route
path = ":tenant/:subscription/manage"
element = {<ManageSubscriptionPage />}
/>
</Routes>
</div>
);
}
В своем «удаленном приложении» вы хотите исключить ведущий «дубликат» tenant сегмент пути.
удаленное приложение App.tsx
function App() {
return (
<div className = "app">
<Routes>
{/* Nothing matches "/tenant/sub/test" */}
<Route
// "/:tenant" matches "/some-tenant"
path = "/"
element = {<TenantPage />}
/>
<Route
// "/:tenant/:subscription" matches "/some-tenant/some-sub"
path = "/:subscription"
element = {<SubscriptionPage />}
/>
<Route
path = "/:subscription/manage"
element = {<ManageSubscriptionPage />}
/>
</Routes>
</div>
);
}
Когда «удаленное приложение» запускается отдельно, вы можете предоставить сегмент корневого tenant пути маршрутизатору через свойство basename, и все маршруты/ссылки/и т. д. будут функционировать относительно этого пути.
import { BrowserRouter } from 'react-rotuer-dom';
...
<BrowserRouter basename = "/some-tenant">
{/* Remote App */}
<RootApp />
</BrowserRouter>
@lestersconyers Почему бы вам не использовать одни и те же маршруты, они не меняются? Можете ли вы уточнить, что вы подразумеваете под «независимым запуском моего удаленного приложения»? Вы имеете в виду, что размещаете и обслуживаете удаленное приложение в другом месте, возможно, в подкаталоге?
Правильный. Когда мы активно разрабатываем, мы хотим воспользоваться преимуществами Vite HMR, поэтому запускаем удаленное приложение отдельно через npm run dev. Не отображается, что HMR доступен при предварительном просмотре.
@lestersconyers Это кажется отдельной проблемой/вопросом. Зависит ли правильность работы удаленного приложения от параметра пути tenant основного приложения? Предположительно, вы отображаете удаленное приложение в маршрутизаторе при изолированной работе, и если вам нужен этот корневой tenant сегмент пути, вы можете указать опорное имя basename на маршрутизаторе и получить доступ к удаленному приложению, как если бы оно обслуживалось из подкаталог.
basename делает свое дело. ``` // удаленное приложение main.tsx const tenant = window.location.pathname.split('/')[1]; ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <BrowserRouter basename = {'/' + tenant} > <App /> </BrowserRouter> </React.StrictMode>, ) ```
Думаю, я плохо разбираюсь в ТАК, ха-ха. Я спросил, как добиться того и другого. Если вы хотите изменить свой ответ, включив в него базовое имя, это будет полезно другим. Спасибо.
Но если я это сделаю, я не смогу использовать тот же путь при независимом запуске удаленного приложения. В этом случае
/окажется на странице клиента, но мне нужен арендатор из пути к местоположению.