각각의 SPA를 하나로 통합하는 방식에는 Linked
와Unified
방식이 존재
// App Shell
import React, { lazy, Suspense } from 'react';
import { Navigate, ReactObject } from 'react-router-dom';
import { Layout } from '@/components/layout'
import { app1RoutingPrefix, app2RoutingPrefix } from '@/constants';
import App1Lazy = lazy(() => import("../components/App1"));
import App2Lazy = lazy(() => import("../components/App2"));
export const routes: ReactObject[] => [
{
path: '/',
element: <Layout />,
children: [
{
index: true,
element: <Navigate to={`/${app1RoutingPrefix}`} />,
},
{
path: `${app1RoutingPrefix}/*`,
element: <Suspense fallback="Loading App1..."><App1Lazy /></Suspense>,
},
{
path: `${app2RoutingPrefix}/*`,
element: <Suspense fallback="Loading App2..."><App2Lazy /></Suspense>,
}
]
}
]
// App1.tsx
useEffect(() => {
if (!isFirstRunRef.current) return;
// module federation을 통해 가져온 'mount'라는 함수를 이용
unmountRef.current = mount({
mountPoint: wrapperRef.current!,
initialPathname: location.pathname.replace(app1Basename, ''),
});
isFirstRunRef.current = false;
}, [location])
useEffect(() => unmountRef.current, []);
return <div ref={wrapperRef} id="app1-mfe" />;
import React from 'react';
import { createRoot } from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import { createRouter } from '@/routing/router-factory';
import { RoutingStrategy } from '@/routing/types';
interface Mount {
mountPoint: HTMLElement;
initialPathname?: string;
routingStrategy?: RoutingStrategy;
}
export const mount = ({
mountPoint,
initialPathname,
routingStrategy,
}: Mount) => {
// 마이크로 앱들은 또하나의 react-app 이기 때문에 react router가 독자적으로 구성됨
const router = createRouter({ strategy: routingStrategy, initialPathname });
const root = createRoot(mountPoint);
root.render(<RouterProvider router={router} />);
return () => queueMicrotask(() => root.unmount());
}
import React from 'react';
import { Outlet } from 'react-router-dom';
import { NavigationManager } from '@/components/navigation';
import { Page1, Page2 } from '@/pages';
export const routes = [
{
path: "/",
element: (
<NavigationManager>
<Outlet>
</NavigationManager>
),
children: [
{
index: true,
element: <Page1 />,
},
{
path: 'page-1,
element: <Page1 />,
},
{
path: 'page-2,
element: <Page2 />,
}
]
}
];