useModuleApps
Returns the React components of all micro-front-end sub-applications, allowing for flexible control over routing.
Usage
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';
 
Function Signature
function useModuleApps(): Record<string, React.FC<any>>
Returns the React components wrapped around each subapp.
Example
You need to configure the micro-front-end sub-application information first.
modern.config.ts
import { appTools, defineConfig } from '@modern-js/app-tools';
import { garfishPlugin } from '@modern-js/plugin-garfish';
export default defineConfig({
  runtime: {
    router: true,
  },
  plugins: [appTools(), garfishPlugin()],
});
 
src/modern.runtime.ts
import { defineRuntimeConfig } from '@modern-js/runtime';
export default defineRuntimeConfig({
  masterApp: {
    apps: [{
      name: 'Table',
      entry: 'http://localhost:8081',
      // activeWhen: '/table'
    }, {
      name: 'Dashboard',
      entry: 'http://localhost:8082'
      // activeWhen: '/dashboard'
    }]
  },
});
 
App.tsx
function App() {
  const { Home, Contact } = useModuleApps();
  return (
    <div>
      Master APP
      <Route exact path="/home">
        <Home />
      </Route>
      <Route exact path="/home">
        <Contact />
      </Route>
    </div>
  );
}
defineConfig(App, {
  masterApp: {
    apps: [
      {
        // name is case-sensitive, what name provides is what useModuleApps returns
        name: 'Home',
        entry: 'http://127.0.0.1:8081/',
      },
      {
        name: 'Contact',
        entry: 'http://localhost:8082',
      },
    ],
  },
});
 
Get the Home and Contact sub-application components(the same as name in the config) through useModuleApps(). After that, you can load the child application just like a normal React component.
Centralized Routing
Centralized Routing is a way to centrally configure the activation routes of sub-applications. Add activeWhen config to enable Centralized Routing.
src/modern.runtime.ts
import { defineRuntimeConfig } from '@modern-js/runtime';
export default defineRuntimeConfig({
  masterApp: {
    apps: [{
      name: 'Table',
      entry: 'http://localhost:8081',
      // activeWhen: '/table'
    }, {
      name: 'Dashboard',
      entry: 'http://localhost:8082'
      // activeWhen: '/dashboard'
    }]
  },
});
 
Then use the useModuleApp method to get the MApp component in the main application, and render the MApp in the main application.
main: App.tsx
import { useModuleApp } from '@modern-js/plugin-runtime';
function App() {
  const { MApp } = useModuleApps();
  return (
    <div>
      <MApp />
    </div>
  );
}
defineConfig(App, {
  masterApp: {
    apps: [
      {
        // name is case sensitive, what name provides is what useModuleApps returns
        name: 'Dashboard',
        activeWhen: '/dashboard',
        entry: 'http://127.0.0.1:8081/',
      },
      {
        name: 'TableList',
        activeWhen: '/table',
        entry: 'http://localhost:8082',
      },
    ],
  },
});
 
After starting the application in this way, accessing the /dashboard route will render the Dashboard, and accessing the /table route will render the TableList.
Load Animation
You can customize the transition animation of the component loading process as follows.
App.tsx
function App() {
  const {
    Components: { Home },
  } = useModuleApps();
  return (
    <div>
      Master APP
      <Route exact path="/home">
        <Home
          loadable={{
            loading: ({ pastDelay, error }: any) => {
              if (error) {
                console.error(error);
                return <div>error: {error?.message}</div>;
              } else if (pastDelay) {
                return <div>loading</div>;
              } else {
                return null;
              }
            },
          }}
        />
      </Route>
    </div>
  );
}