diff --git a/.changeset/beige-pears-jog.md b/.changeset/beige-pears-jog.md new file mode 100644 index 000000000000..68f9d0846350 --- /dev/null +++ b/.changeset/beige-pears-jog.md @@ -0,0 +1,5 @@ +--- +'@modern-js/plugin-garfish': patch +--- + +fix(plugin-garfish): basename calculation polish diff --git a/packages/document/main-doc/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx b/packages/document/main-doc/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx index ac05269681b2..f46e8b40877f 100644 --- a/packages/document/main-doc/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx +++ b/packages/document/main-doc/docs/en/guides/topic-detail/micro-frontend/c02-development.mdx @@ -151,8 +151,9 @@ import { Tab, Tabs } from 'rspress/theme'; ```tsx import { useLocation, useHref } from 'react-router-dom'; const App = () => { + const basename = useHref('/table'); const { Table } = useModuleApps(); - return ; + return
; }; ``` @@ -160,16 +161,8 @@ const App = () => { ```tsx import { useLocation, useHistory } from 'react-router-dom'; const App = () => { - const { Table } = useModuleApps(); - return
; -}; -``` - - -```tsx -import { useLocation, useHref } from 'react-router-dom'; -const App = () => { - const basename = useHref('/table'); + const history = useHistory(); + const basename = history.createHref({ pathname: '/table' }); const { Table } = useModuleApps(); return
; }; diff --git a/packages/document/main-doc/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx b/packages/document/main-doc/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx index 4a3b7f5ccc96..bca453bf839d 100644 --- a/packages/document/main-doc/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx +++ b/packages/document/main-doc/docs/zh/guides/topic-detail/micro-frontend/c02-development.mdx @@ -155,8 +155,9 @@ import { Tab, Tabs } from 'rspress/theme'; ```tsx import { useLocation, useHref } from 'react-router-dom'; const App = () => { + const basename = useHref('/table'); const { Table } = useModuleApps(); - return
; + return
; }; ``` @@ -164,16 +165,8 @@ const App = () => { ```tsx import { useLocation, useHistory } from 'react-router-dom'; const App = () => { - const { Table } = useModuleApps(); - return
; -}; -``` - - -```tsx -import { useLocation, useHref } from 'react-router-dom'; -const App = () => { - const basename = useHref('/table'); + const history = useHistory(); + const basename = history.createHref({ pathname: '/table' }); const { Table } = useModuleApps(); return
; }; diff --git a/packages/runtime/plugin-garfish/src/runtime/loadable.tsx b/packages/runtime/plugin-garfish/src/runtime/loadable.tsx index d4165e883b76..2dad2ea7c07a 100644 --- a/packages/runtime/plugin-garfish/src/runtime/loadable.tsx +++ b/packages/runtime/plugin-garfish/src/runtime/loadable.tsx @@ -20,9 +20,11 @@ export interface MicroProps { [key: string]: any; // just for type hint to users - useHref?: any; useLocation?: any; + useHref?: any; useHistory?: any; + useRouteMatch?: any; + useMatches?: any; } const DEFAULT_LOADABLE = { diff --git a/packages/runtime/plugin-garfish/src/runtime/utils/apps.tsx b/packages/runtime/plugin-garfish/src/runtime/utils/apps.tsx index 09454fc23a85..063df39eb9ec 100644 --- a/packages/runtime/plugin-garfish/src/runtime/utils/apps.tsx +++ b/packages/runtime/plugin-garfish/src/runtime/utils/apps.tsx @@ -48,11 +48,14 @@ function getAppInstance( React.ComponentType | undefined >(); const context = useContext(RuntimeReactContext); - + const useRouteMatch = props.useRouteMatch ?? context?.router?.useRouteMatch; + const useMatches = props.useMatches ?? context?.router?.useMatches; const useLocation = props.useLocation ?? context?.router?.useLocation; - const useHref = props.useHref ?? context?.router?.useHref; const useHistory = props.useHistory ?? context?.router?.useHistory; - const isRouterV5 = Boolean(useHistory); + const useHref = props.useHistory ?? context?.router?.useHref; + + const match = useRouteMatch?.(); + const matchs = useMatches?.(); if (!useLocation) { console.warn( @@ -68,37 +71,51 @@ or directly pass the "basename": `, ); } - const location = useLocation(); - let basename = ''; - const activeWhen = appInfo.activeWhen as string; + const location = useLocation(); - // 1. options.basename in edenx.config.ts /** - * e.g: - masterApp: { - basename: '/main-app-basename' - }, + * main-app basename: /main-basename + * sub-app basename: /main-basename/sub-active-path */ - if (options?.basename && typeof options.basename === 'string') { - basename = pathJoin(options.basename, activeWhen); - } - // 2. use hooks to calculate the basename automatically - if (isRouterV5) { + // 1. handle the main-app basename + /** + * `options?.basename` comes from + * masterApp: { + * basename: '/main-app-basename' + * }, + */ + let basename = options?.basename || '/'; + if (useHistory /* react-router@5 */) { // there is no dynamic switching of the router version in the project // so hooks can be used in conditional judgment // eslint-disable-next-line react-hooks/rules-of-hooks const history = useHistory?.(); // To be compatible to history@4.10.1 and @5.3.0 we cannot write like this `history.createHref(pathname)` - basename = history?.createHref?.({ pathname: activeWhen }); - } else if (useHref) { + basename = history?.createHref?.({ pathname: '/' }); + } else if (useHref /* react-router@6 */) { // eslint-disable-next-line react-hooks/rules-of-hooks - basename = useHref?.(activeWhen); + basename = useHref?.('/'); + } + + // 2. handle the subActivePath and `pathJoin(mainBasename, subActivePath)` + if (matchs && matchs.length > 0 /* react-router@6 */) { + const matchItem = { + ...matchs[matchs.length - 1], + }; + for (const key in matchItem.params) { + matchItem.pathname = matchItem.pathname.replace( + new RegExp(`/${matchItem.params[key]}$`), + '', + ); + } + basename = pathJoin(basename, matchItem.pathname || '/'); + } else if (match /* react-router@5 */) { + basename = pathJoin(basename, match?.path || '/'); } - // 3. props.basename - // props.basename has the highest priority + // 3. props.basename has the highest priority // e.g: if (props.basename && typeof props.basename === 'string') { // eslint-disable-next-line prefer-destructuring diff --git a/packages/runtime/plugin-garfish/tests/index.test.tsx b/packages/runtime/plugin-garfish/tests/index.test.tsx index 18b3a91d0bee..5d29c4a84d6a 100644 --- a/packages/runtime/plugin-garfish/tests/index.test.tsx +++ b/packages/runtime/plugin-garfish/tests/index.test.tsx @@ -14,6 +14,7 @@ import { useHistory, BrowserRouter, MemoryRouter, + useRouteMatch, } from '@modern-js/plugin-router-v5/runtime'; import garfishPlugin from '../src/runtime'; import { useModuleApps } from '../src'; @@ -185,7 +186,7 @@ describe('plugin-garfish', () => { unmount(); }); - test('useModuleApps hook should set basename for sub-app automatically by createHref', async () => { + test('useModuleApps hook should set basename for sub-app by props.basename', async () => { const basenameTest = { name: 'BasenameTest', activeWhen: '/basename-test', @@ -240,7 +241,7 @@ describe('plugin-garfish', () => { @@ -258,17 +259,14 @@ describe('plugin-garfish', () => { render(, {}); }); - // expect(screen.getByTestId('home-title')).not.toBeInTheDocument(); - expect( - await screen.findByText('sub-app basename: /main-app/basename-test'), + await screen.findByText('sub-app basename: /main-app/basename-props-has-highest-priority'), ).toBeInTheDocument(); }); - test('useModuleApps sub-app basename can be set by user defineConfig masterApp.apps options', async () => { + test('useModuleApps should set basename for sub-app based on last RouterMatch when no activeWhen', async () => { const basenameTest = { name: 'BasenameTest', - activeWhen: '/basename-appInfo-options', entry: basenameTestPath, // Each test does not affect with each other. @@ -286,7 +284,7 @@ describe('plugin-garfish', () => { }, basename: '/main-app', }; - window.location.assign('/main-app/basename-appInfo-options/some-test'); + window.location.assign('/main-app/no-active-when/some-test'); const App = () => { const { BasenameTest } = useModuleApps(); @@ -297,7 +295,14 @@ describe('plugin-garfish', () => { return ( - + + + + + ); @@ -311,9 +316,7 @@ describe('plugin-garfish', () => { }); expect( - await screen.findByText( - 'sub-app basename: /main-app/basename-appInfo-options', - ), + await screen.findByText('sub-app basename: /main-app/no-active-when'), ).toBeInTheDocument(); }); });