Skip to content

Commit

Permalink
docs: Documented the AppRouter component (#110)
Browse files Browse the repository at this point in the history
* Added reference docs for AppRouter

* Updated docs and removed axios

* Removed axios from the documentation

* Updated documentation

* Updating existing documentation to use AppRouter

* Updated pnpm lock file

* Fixed linting
  • Loading branch information
patricklafrance authored Nov 9, 2023
1 parent 233057c commit 5c8bc11
Show file tree
Hide file tree
Showing 40 changed files with 1,158 additions and 910 deletions.
40 changes: 11 additions & 29 deletions docs/getting-started/create-host.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ Create a new application (we'll refer to ours as `host`), then open a terminal a
+++ pnpm
```bash
pnpm add -D @workleap/webpack-configs @workleap/swc-configs @workleap/browserslist-config webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript
pnpm add @squide/core @squide/react-router @squide/webpack-module-federation react react-dom react-router-dom
pnpm add @squide/core @squide/react-router @squide/webpack-module-federation @squide/msw @squide/firefly react react-dom react-router-dom
```
+++ yarn
```bash
yarn add -D @workleap/webpack-configs @workleap/swc-configs @workleap/browserslist-config webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript
yarn add @squide/core @squide/react-router @squide/webpack-module-federation react react-dom react-router-dom
yarn add @squide/core @squide/react-router @squide/webpack-module-federation @squide/msw @squide/firefly react react-dom react-router-dom
```
+++ npm
```bash
npm install -D @workleap/webpack-configs @workleap/swc-configs @workleap/browserslist-config webpack webpack-dev-server webpack-cli @swc/core @swc/helpers browserslist postcss typescript
npm install @squide/core @squide/react-router @squide/webpack-module-federation react react-dom react-router-dom
npm install @squide/core @squide/react-router @squide/webpack-module-federation @squide/msw @squide/firefly react react-dom react-router-dom
```
+++

Expand Down Expand Up @@ -115,36 +115,18 @@ root.render(
);
```

Then, retrieve the routes that have been registered by the remote module with the [useRoutes](/reference/runtime/useRoutes.md) hook and create a router instance:
Then, render the [AppRouter](../reference/routing/appRouter.md) component. The `AppRouter` component will render a React Router [browser instance](https://reactrouter.com/en/main/routers/create-browser-router) configured with the registered routes:

```tsx !#10,13,17 host/src/App.tsx
import { useMemo } from "react";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { useRoutes } from "@squide/react-router";
import { useAreModulesReady } from "@squide/webpack-module-federation";
import { RootLayout } from "./RootLayout.tsx";
import { Home } from "./Home.tsx";
```tsx host/src/App.tsx
import { AppRouter } from "@squide/firefly";

export function App() {
// Re-render the application once the remote modules are registered.
const areModulesReady = useAreModulesReady();

// Retrieve the routes registered by the remote modules.
const routes = useRoutes();

// Create the router instance with the registered routes.
const router = useMemo(() => {
return createBrowserRouter(routes);
}, [routes]);

// Display a loading until the remote modules are registered.
if (!areModulesReady) {
return <div>Loading...</div>;
}

// Render the router.
return (
<RouterProvider router={router} />
<AppRouter
fallbackElement={<div>Loading...</div>}
errorElement={<div>An error occured!</div>}
waitForMsw={false}
/>
);
}
```
Expand Down
5 changes: 4 additions & 1 deletion docs/getting-started/learn-the-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,5 +233,8 @@ if (process.env.USE_MSW) {

## Fakes

For development purposes, have a look at the available [fake implementations](../reference/default.md#fakes).
Take a look at the [fake implementations](../reference/default.md#fakes). These implementations are designed to facilitate the set up of a module isolated environment.

## Guides

Explore the [guides](../guides/default.md) to learn about Squide advanced features.
36 changes: 14 additions & 22 deletions docs/guides/develop-a-module-in-isolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,18 @@ First, create a new package (we'll refer to ours as `shell`) and add the followi

Then, install the package dependencies and configure the new package with [tsup](https://gsoft-inc.github.io/wl-web-configs/tsup/).

Then, create a `AppRouter` component in the shell package to provide a **reusable router configuration** that can be utilized by both the host application and the isolated modules.
Then, create a `AppRouter` component in the shell package to provide a **reusable router configuration** that can be utilized by both the host application and the isolated modules. The new `AppRouter` component should be based on the `@squide/firefly` [AppRouter](../reference/routing/appRouter.md) component:

```tsx shell/src/AppRouter.tsx
import { useRoutes } from "@squide/react-router";
import { useAreModulesReady } from "@squide/webpack-module-federation";
import { useMemo } from "react";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { AppRouter as FireflyAppRouter } from "@squide/firefly";

export function AppRouter() {
const routes = useRoutes();

// Re-render the app once all the remotes are registered, otherwise the remotes routes won't be added to the router.
const areModulesReady = useAreModulesReady();

const router = useMemo(() => {
return createBrowserRouter(routes);
}, [routes]);

if (!areModulesReady) {
return <div>Loading...</div>;
}

return (
<RouterProvider router={router} />
<FireflyAppRouter
fallbackElement={<div>Loading...</div>}
errorElement={<div>An error occured!</div>}
waitForMsw={false}
/>
);
}
```
Expand Down Expand Up @@ -121,7 +109,9 @@ Then, incorporate the newly introduced `AppRouter` component:
import { AppRouter } from "@sample/shell";

export function App() {
return <AppRouter />
return (
<AppRouter />
);
}
```

Expand Down Expand Up @@ -233,7 +223,9 @@ The `App.tsx` file uses the newly created `AppRouter` component to setup [React
import { AppRouter } from "@sample/shell";

export function App() {
return <AppRouter />;
return (
<AppRouter />
);
}
```

Expand Down Expand Up @@ -381,7 +373,7 @@ This file is similar to the `index.tsx` file of the [remote module](#indextsx).

This file is similar to the `App.tsx` file of the [remote module](#apptsx).

### DevHome.tsx & registerDev
### DevHome.tsx and registerDev

These files are similar to the `dev/DevHome.tsx` and `dev/register.tsx` files of the [remote module](#devhometsx).

Expand Down
23 changes: 6 additions & 17 deletions docs/guides/isolate-module-failures.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,15 @@ Nevertheless, an application can get very close to iframes failure isolation by
In the following code sample, a `RootErrorBoundary` is declared below the `RootLayout` but above the routes of the module. By doing so, if a module encounters an unhandled error, the nested error boundary will only replace the section rendered by the `Outlet` component within the `RootLayout` rather than the entire page:

```tsx host/src/App.tsx
import { useMemo } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { useAreModulesReady } from "@squide/webpack-module-federation";
import { useRoutes } from "@squide/react-router";
import { AppRouter } from "@squide/firefly";

export function App() {
const areModulesReady = useAreModulesReady();

const routes = useRoutes();

const router = useMemo(() => {
return createBrowserRouter(routes);
}, [routes]);

if (!areModulesReady) {
return <div>Loading...</div>;
}

return (
<RouterProvider router={router} />
<AppRouter
fallbackElement={<div>Loading...</div>}
errorElement={<div>An error occured!</div>}
waitForMsw={false}
/>
);
}
```
Expand Down
66 changes: 22 additions & 44 deletions docs/guides/override-a-react-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,18 @@ In a federated application using [Module Federation](https://webpack.js.org/conc

Let's take a simple example using a `BackgroundColorContext`:

```tsx !#21,23 host/src/App.tsx
import { useMemo } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { useAreModulesReady } from "@squide/webpack-module-federation";
import { useRoutes } from "@squide/react-router";
```tsx !#6,12 host/src/App.tsx
import { AppRouter } from "@squide/firefly";
import { BackgroundColorContext } from "@sample/shared";

export function App() {
const areModulesReady = useAreModulesReady();

const routes = useRoutes();

const router = useMemo(() => {
return createBrowserRouter(routes);
}, [routes]);

if (!areModulesReady) {
return <div>Loading...</div>;
}

return (
<BackgroundColorContext.Provider value="blue">
<RouterProvider router={router} />
<AppRouter
fallbackElement={<div>Loading...</div>}
errorElement={<div>An error occured!</div>}
waitForMsw={false}
/>
</BackgroundColorContext.Provider>
);
}
Expand Down Expand Up @@ -86,59 +75,48 @@ export const register: ModuleRegisterFunction<Runtime> = runtime => {
}
```

### Extract an utility function
### Extract an utility component

Since there are multiple routes to setup with the new provider, an utility function can be extracted:
Since there are multiple routes to setup with the new provider, an utility component can be extracted:

```tsx !#6-12,17 remote-module/src/register.tsx
import type { ModuleRegisterFunction, Runtime } from "@squide/react-router";
import { BackgroundColorContext } from "@sample/shared";
import { ColoredPage } from "./ColoredPage.tsx";
import type { ReactElement } from "react";
import type { ReactNode } from "react";

function withRedBackground(page: ReactElement) {
function RedBackground({ children }: { children: ReactNode }) {
return (
<BackgroundColorContext.Provider value="red">
{page}
{children}
</BackgroundColorContext.Provider>
)
);
}

export const register: ModuleRegisterFunction<Runtime> = runtime => {
runtime.registerRoute({
path: "/colored-page",
element: withRedBackground(<ColoredPage />)
element: <RedBackground><ColoredPage /></RedBackground>
});
}
```

## Update a singleton dependency version

Let's consider a more specific use case where the host application declares a `ThemeContext` from Workleap's new design system, Hopper:
Let's consider a more specific use case where the host application declares a `ThemeContext` from Workleap's new design system, [Hopper](https://hopper.workleap.design/):

```tsx !#21,23 host/src/App.tsx
import { useMemo } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { useAreModulesReady } from "@squide/webpack-module-federation";
import { useRoutes } from "@squide/react-router";
```tsx !#6,12 host/src/App.tsx
import { AppRouter } from "@squide/firefly";
import { ThemeContext } from "@hopper/components";

export function App() {
const areModulesReady = useAreModulesReady();

const routes = useRoutes();

const router = useMemo(() => {
return createBrowserRouter(routes);
}, [routes]);

if (!areModulesReady) {
return <div>Loading...</div>;
}

return (
<ThemeContext.Provider value="dark">
<RouterProvider router={router} />
<AppRouter
fallbackElement={<div>Loading...</div>}
errorElement={<div>An error occured!</div>}
waitForMsw={false}
/>
</ThemeContext.Provider>
);
}
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/override-the-host-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Package managers supporting workspaces such as Yarn and NPM call this mechanism

Squide has a built-in [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) functionality capable of raising module routes marked as `hoist` at the root of the routes array, before the `RootLayout` declaration. Thus, an hoisted page will not be wrapped by the `RootLayout` (or the `AuthenticationBoundary`) and will have full control over its rendering.

To hoist module pages, simple add the [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) option to the route options at registration and optionally use a new layout:
To hoist module pages, add the [hoist](../reference/runtime/runtime-class.md#register-an-hoisted-route) option to the route registration options and optionally use a different layout:

```tsx !#9,12,22 local-module/src/register.tsx
import type { ModuleRegisterFunction, Runtime } from "@squide/react-router";
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ expanded: true

### Routing

- [AppRouter](routing/AppRouter.md)
- [ManagedRoutes](routing/ManagedRoutes.md)
- [useRenderedNavigationItems](routing/useRenderedNavigationItems.md)
- [useRouteMatch](routing/useRouteMatch.md)
Expand Down Expand Up @@ -74,6 +75,6 @@ expanded: true

## Fakes

Squide offers a collection of fake implementations to facilitate the development of modules in isolation from the other parts of the application.
Squide offers a collection of fake implementations designed to facilitate the set up of a module isolated environment.

- [LocalStorageSessionManager](fakes/LocalStorageSessionManager.md)
2 changes: 1 addition & 1 deletion docs/reference/fakes/index.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
order: -10
order: -20
2 changes: 1 addition & 1 deletion docs/reference/logging/index.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
order: 60
order: 50
2 changes: 1 addition & 1 deletion docs/reference/messaging/index.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
order: 50
order: 40
2 changes: 1 addition & 1 deletion docs/reference/msw/index.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
order: 0
order: -10
label: "Mock Service Worker"
4 changes: 4 additions & 0 deletions docs/reference/msw/useIsMswReady.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Force the application to re-render once [Mock Service Worker](https://mswjs.io/) (MSW) is started. Without this hook, the page is rendered before all the request handlers are registered to MSW which could results in 404 errors.

!!!info
If your application is using the [AppRouter](../routing/appRouter.md) component, there's no need for this hook.
!!!

## Reference

```ts
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/plugins/index.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
order: 20
order: 10
label: "Plugins"
8 changes: 4 additions & 4 deletions docs/reference/registration/completeModuleRegistrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ completeModuleRegistrations(runtime, data?)
### Complete module registrations
```tsx !#16-17,24 host/src/bootstrap.tsx
import { completeLocalModuleRegistrations, registerLocalModules, Runtime } from "@squide/react-router";
import { completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/webpack-module-federation";
import { registerLocalModules, Runtime } from "@squide/react-router";
import { completeModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/webpack-module-federation";
import { register } from "@sample/local-module";
import { fetchFeatureFlags, type AppContext } from "@sample/shared";

Expand Down Expand Up @@ -97,8 +97,8 @@ export const register: ModuleRegisterFunction<Runtime, AppContext, DeferredRegis
### Handle the completion errors
```tsx !#23-31 host/src/bootstrap.tsx
import { completeLocalModuleRegistrations, registerLocalModules, Runtime } from "@squide/react-router";
import { completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/webpack-module-federation";
import { registerLocalModules, Runtime } from "@squide/react-router";
import { completeModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/webpack-module-federation";
import { register } from "@sample/local-module";
import { fetchFeatureFlags, type AppContext } from "@sample/shared";

Expand Down
4 changes: 4 additions & 0 deletions docs/reference/registration/useAreModulesReady.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ toc:

Force the application to re-render once the registration process has been completed for all the modules. Without this hook, the page is rendered with an empty router as it happens before the remote modules registered their routes and navigation items.

!!!info
If your application is using the [AppRouter](../routing/appRouter.md) component, there's no need for this hook.
!!!

!!!info
If your application supports [deferred registrations](./registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items), make sure to pair this hook with the [useAreModulesRegistered](./useAreModulesRegistered.md) hook.
!!!
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/registration/useAreModulesRegistered.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ order: 50

Force the application to re-render once all the modules are registered (but not ready).

!!!info
If your application is using the [AppRouter](../routing/appRouter.md) component, there's no need for this hook.
!!!

!!!info
This hook should only be used by applications that support [deferred registrations](./registerRemoteModules.md#defer-the-registration-of-routes-or-navigation-items) and should be pair with the [useAreModulesReady](./useAreModulesReady.md) hook.
!!!
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/routing/ManagedRoutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ runtime.registerRoute({
}, { hoist: true });
```

### Parameters
### Properties

None

Expand Down
Loading

0 comments on commit 5c8bc11

Please sign in to comment.