Experience Micro Frontend

Through this chapter you can learn:

  • How to create the main application and sub-application of the micro frontend project.
  • Basic process of micro frontend project development.

Create an app

Currently supports two routing modes

  • Self-controlled routing
  • Conventional routing

First, clarify the routing mode of the main application create a conventional routing main application or create a self-controlled routing main application

In this experience we will create two sub-applications Table and Dashboard for the main application (Table is reduced routing, Dashboard is self-controlled routing)

File-based Routing Main App

Initialize the project with a command line:

mkdir masterApp && cd masterApp
npx @modern-js/create@latest

After the project is created, we can enable the micro frontend through pnpm run new:

? Please select the operation you want: Enable features
? Please select the feature name: Enable Micro Front-end Feature

Next, let's register the micro frontend plugin and add the main micro frontend app and add the list of sub-apps:

modern.config.ts
import appTools, { defineConfig } from '@modern-js/app-tools';
import garfishPlugin from '@modern-js/plugin-garfish';

export default defineConfig({
  runtime: {
    router: true,
    masterApp: {
      apps: [{
        name: 'Table',
        entry: 'http://localhost:8081',
        // activeWhen: '/table'
      }, {
        name: 'Dashboard',
        entry: 'http://localhost:8082'
        // activeWhen: '/dashboard'
      }]
    },
  },
  plugins: [appTools(), garfishPlugin()],
});

Then we create two new directories in the routes folder

  • table (for loading conventional routing sub-applications)
  • dashboard (for loading self-controlled routing sub-applications)

In these two directories, we need to create a $.tsx file as the entry of the main application convention route ($represents fuzzy match, that is, /table and /table/test will match this $.tsx as the entry file of the route, which will ensure that the sub-application route is loaded correctly in the micro frontend scenario)

Load file-base routing sub-app

src/routes/table/$.tsx
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';

const Index = () => {
  const { Table } = useModuleApps();

  return (
    <div>
      <Table />
    </div>
  )
}

export default Index;

Load self-controlled routing sub-app

src/routes/dashboard/$.tsx
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';

const Index = () => {
  const { Dashboard } = useModuleApps();

  return (
    <div>
      <Dashboard />
    </div>
  )
}

export default Index;

At this time, the main application configuration has been completed, and the sub-application can be loaded through the route, and the layout.tsx of the main application can be modified to jump to the route:

src/route/layout.tsx
import { Outlet, Link } from '@modern-js/runtime/router';

const Layout = () => (
  <div>
    <div><Link to={'/table'}>Load file-base routing sub-app</Link></div>
    <div><Link to={'/dashboard'}>Load self-controlled routing sub-app</Link></div>
    <div><Link to={'/'}>unmount sub-app</Link></div>
    <Outlet />
  </div>
);

export default Layout;

Self-Controlled Main App

Initialize the project with a command line:

mkdir masterApp && cd masterApp
npx @modern-js/create@latest

After the project is created, we can enable the micro frontend function through pnpm run new:

? Please select the operation you want: Enable features
? Please select the feature name: Enable Micro Front-end Feature

Next, let's register the micro frontend plugin and add the main micro frontend app and add the list of sub-apps:

modern.config.ts
import appTools, { defineConfig } from '@modern-js/app-tools';
import garfishPlugin from '@modern-js/plugin-garfish';

export default defineConfig({
  runtime: {
    router: true,
    masterApp: {
      apps: [{
        name: 'Table',
        entry: 'http://localhost:8081',
        // activeWhen: '/table'
      }, {
        name: 'Dashboard',
        entry: 'http://localhost:8082'
        // activeWhen: '/dashboard'
      }]
    },
  },
  plugins: [appTools(), garfishPlugin()],
});

Since it is a self-controlled route, we delete the routes/ folder and add the App.tsx file in the src/ directory. If you use a non-MApp component here, you need to use the createBrowserRouter API of '=React Router v6 to create routes.

Load sub-app

src/App.tsx
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';

import { RouterProvider, Route, createBrowserRouter, createRoutesFromElements, BrowserRouter, Link, Outlet } from '@modern-js/runtime/router';

const AppLayout = () => (
  <>
    <div><Link to={'/table'}>加载约定式路由子应用</Link></div>
    <div><Link to={'/dashboard'}>加载自控式路由子应用</Link></div>
    <div><Link to={'/'}>卸载子应用</Link></div>
    <Outlet />
  </>
)

export default () => {
  const { apps, MApp, Table, Dashboard } = useModuleApps();

  // 使用的不是 MApp 组件,需要使用 createBrowserRouter 来创建路由
  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path="/" element={<AppLayout />}>
        <Route key={'table'} path={'table/*'} element={<Table />} />
        <Route key={'dashboard'} path={'dashboard/*'} element={<Dashboard />} />
      </Route>
    )
  );

  return (
    // 方法一:使用 MApp 自动根据配置的 activeWhen 参数加载子应用(本项目配置在 modern.config.ts 中)
    // <BrowserRouter>
    //   <MApp />
    // </BrowserRouter>

    // 方法二:手动写 Route 组件方式加载子应用,方便于需要鉴权等需要前置操作的场景
    <>
      <RouterProvider router={router} />
    </>
  );
};

File-based sub-app

Initialize the project with a command line:

mkdir table && cd table
npx @modern-js/create@latest

After create sub-app. We execute pnpm run new to enable the micro frontend function:

? Please select the operation you want: Enable features
? Please select the feature name: Enable Micro Front-end Feature

Next, let's register the micro frontend plugin and modify modern.config.ts to add the configuration of the micro frontend sub-app deploy.microFrontend:

modern.config.ts
import appTools, { defineConfig } from '@modern-js/app-tools';
import garfishPlugin from '@modern-js/plugin-garfish';

export default defineConfig({
  dev: {
    port: 8081
  },
  runtime: {
    router: true,
    state: true,
  },
  deploy: {
    microFrontend: true,
  },
  plugins: [appTools(), garfishPlugin()],
});

add src/routes/page.tsx:

src/routes/page.tsx
const Index = () => {
  return (
    <div className="container-box">subApp</div>
  )
}

export default Index;

Self-controlled sub-app

Initialize the project with a command line:

mkdir table && cd table
npx @modern-js/create@latest

After create sub-app. We execute pnpm run new to enable the micro frontend function:

? Please select the operation you want: Enable features
? Please select the feature name: Enable Micro Front-end Feature

Next, let's register the micro frontend plugin and modify modern.config.ts to add the configuration of the micro frontend sub-app deploy.microFrontend:

modern.config.ts
import appTools, { defineConfig } from '@modern-js/app-tools';
import garfishPlugin from '@modern-js/plugin-garfish';

export default defineConfig({
  dev: {
    port: 8082
  },
  runtime: {
    router: true,
    state: true,
  },
  deploy: {
    microFrontend: true,
  },
  plugins: [appTools(), garfishPlugin()],
});

Self-controlled routing needs to delete the routes/ folder and create a new App.tsx in the src/ directory.

And add code in src/App.tsx, note that you need to parse from props and pass basename to BrowserRouter.

src/App.tsx
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';

export default (props: {basename: string}) => {
  const { basename } = props;

  return (
    <BrowserRouter basename={basename}>
      <Routes>
        <Route index element={<div>Self-controlled route root</div>} />
        <Route path={'path'} element={<div>Self-controlled sub route</div>} />
      </Routes>
    </BrowserRouter>
  );
};

Debug

Start the application by executing the pnpm run dev command in the directory in sequence:

  • masterApp http://localhost:8080
  • table subapplication (conventional routing) http://localhost:8081
  • dashboard subapplication (self-controlled routing) http://localhost:8082

Access the main application address http://localhost:8080

After completing the experience of the overall development process of micro frontend, you can learn more about how to develop the main application.

FAQ

Garfish issue: https://www.garfishjs.org/issues/