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
The routing modes of the current project are divided into the following three types:
- File-based routing (
router: true
and file-based)
- Self-Controlled routing (
router: true
and create BrowserRouter
)
- Other (
router: false
and independent installation of react-router-dom
in the project)
First, clarify the routing mode of the main application create a file-based routing main App or create a self-controlled main App
In this tutorial 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,
state: true,
masterApp: true,
},
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;
route link
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,
state: true,
masterApp: true,
},
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'}>Loading conventional routed sub-applications</Link></div>
<div><Link to={'/dashboard'}>Loading Self-Controlled Routing Sub-Applications</Link></div>
<div><Link to={'/'}>Uninstall a sub-application</Link></div>
<Outlet />
</>
)
export default () => {
const { apps, MApp, Table, Dashboard } = useModuleApps();
// If you are not using the MApp component, you need to use createBrowserRouter to create the route.
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<AppLayout />}>
<Route key={'table'} path={'table/*'} element={<Table />} />
<Route key={'dashboard'} path={'dashboard/*'} element={<Dashboard />} />
</Route>
)
);
return (
// Approach 1: Use MApp to automatically load sub-applications based on the configured activeWhen parameter (this project is configured in modern.config.ts)
// <BrowserRouter>
// <MApp />
// </BrowserRouter>
// Approach 2: Manually write Route components to load sub-applications, which is convenient for scenarios that require authentication and other pre-requisite operations
<>
<RouterProvider router={router} />
</>
);
};
Other Main App
Install and use react-router-dom
independently in the project. The only difference from self-controlled routing is that after setting router: false
, plugin-garfish cannot obtain useLocation
, useHref
and other hooks to assist in calculating basename and main and child applications. Route synchronization
import { useLocation, useHref } from 'react-router-dom';
const App = () => {
const basename = useHref('/table');
const { Table } = useModuleApps();
return <Table useLocation={useLocation} basename={basename} />;
};
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/