From febdfb817a7cafd5e11de19ee808dbe278e4da54 Mon Sep 17 00:00:00 2001 From: David Nicholas Date: Fri, 26 Jul 2024 16:15:24 -0700 Subject: [PATCH] small tweaks --- package.json | 4 +- packages/shell/Dockerfile | 14 --- .../shell/src/components/Layout/Layout.tsx | 4 +- packages/shell/src/scenes/Account/Account.tsx | 11 ++- packages/workshop/package.json | 2 +- .../AddingMoreMicroFrontends.tsx | 17 ++-- .../ConfiguringModuleFederation.tsx | 89 ++++++++++++++----- .../FaultTolerance/FaultTolerance.tsx | 20 ++--- .../components/GettingSetup/GettingSetup.tsx | 44 +++++---- .../SettingUpRoutes/SettingUpRoutes.tsx | 9 ++ .../SharingCommonModules.tsx | 40 ++++++++- 11 files changed, 173 insertions(+), 81 deletions(-) delete mode 100644 packages/shell/Dockerfile diff --git a/package.json b/package.json index e841c4d..25d54c1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,9 @@ "name": "enterprise-grade-micro-frontends", "version": "0.0.0", "license": "MIT", - "scripts": {}, + "scripts": { + "start": "nx run-many -t --parallel=10" + }, "private": true, "devDependencies": { "@nx/jest": "18.3.3", diff --git a/packages/shell/Dockerfile b/packages/shell/Dockerfile deleted file mode 100644 index 2bebada..0000000 --- a/packages/shell/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM node:18-alpine3.17 as build - -WORKDIR /app -COPY . /app - -RUN npm install -RUN npm run build - -FROM ubuntu -RUN apt-get update -RUN apt-get install nginx -y -COPY --from=build /app/dist /var/www/html/ -EXPOSE 80 -CMD ["nginx","-g","daemon off;"] \ No newline at end of file diff --git a/packages/shell/src/components/Layout/Layout.tsx b/packages/shell/src/components/Layout/Layout.tsx index 3e0634d..13828ec 100644 --- a/packages/shell/src/components/Layout/Layout.tsx +++ b/packages/shell/src/components/Layout/Layout.tsx @@ -1,4 +1,6 @@ -import { FC, Suspense, lazy } from "react"; +import type { FC } from "react"; + +import { Suspense, lazy } from "react"; import { Navigate, Outlet } from "react-router-dom"; import { Container, Flex } from "@mantine/core"; import { readLocalStorageValue } from "@mantine/hooks"; diff --git a/packages/shell/src/scenes/Account/Account.tsx b/packages/shell/src/scenes/Account/Account.tsx index 219adb7..04c63a5 100644 --- a/packages/shell/src/scenes/Account/Account.tsx +++ b/packages/shell/src/scenes/Account/Account.tsx @@ -1,4 +1,4 @@ -import type { AccountScene } from 'shared/profile'; +import type { FC } from "react"; import { Suspense, lazy } from "react"; import { @@ -13,10 +13,9 @@ import { import { ErrorBoundary } from "react-error-boundary"; import { Link } from "react-router-dom"; -// @ts-ignore -const Account = lazy(() => import("profile/account")); +const Account = lazy(() => import("profile/account")); -const AccountScene: AccountScene = () => { +const AccountScene: FC = () => { return ( }> }> @@ -28,7 +27,7 @@ const AccountScene: AccountScene = () => { export default AccountScene; -const AccountSkeleton = () => { +const AccountSkeleton: FC = () => { return ( @@ -44,7 +43,7 @@ const AccountSkeleton = () => { ); }; -const AccountError = () => { +const AccountError: FC = () => { return ( diff --git a/packages/workshop/package.json b/packages/workshop/package.json index 25d9b75..0b0e245 100644 --- a/packages/workshop/package.json +++ b/packages/workshop/package.json @@ -3,7 +3,7 @@ "private": true, "version": "1.0.0", "scripts": { - "dev": "rsbuild dev --open --port 8080", + "dev": "rsbuild dev --port 8080", "build": "rsbuild build", "preview": "rsbuild preview" }, diff --git a/packages/workshop/src/scenes/Exercises/components/AddingMoreMicroFrontends/AddingMoreMicroFrontends.tsx b/packages/workshop/src/scenes/Exercises/components/AddingMoreMicroFrontends/AddingMoreMicroFrontends.tsx index 7bba7c5..6f9700a 100644 --- a/packages/workshop/src/scenes/Exercises/components/AddingMoreMicroFrontends/AddingMoreMicroFrontends.tsx +++ b/packages/workshop/src/scenes/Exercises/components/AddingMoreMicroFrontends/AddingMoreMicroFrontends.tsx @@ -1,6 +1,6 @@ import type { FC } from "react"; -import { Image, List, Text } from "@mantine/core"; +import { Code, Image, List, Text } from "@mantine/core"; import { CodeHighlight } from "@mantine/code-highlight"; import ExerciseLayout from "../../shared/components/ExerciseLayout"; @@ -19,12 +19,13 @@ const AddingMoreMicroFrontends: FC = () => { a couple of key features for our users – the cart and the search bar. </Text> <Image my="lg" src={header} /> + <Text> Both features are MFEs the Header needs to consume. You may continue - from your work on Exercise 3, or check out a clean branch using the - command below. + from your work on the previous exercise, or check out a clean branch + using the command below. </Text> - <CodeHighlight my="lg" lang="console" code="git checkout exercise-4" /> + <CodeHighlight my="lg" code="git checkout soln/fault-tolerance" /> <Text pt="md"> Configure the order and catalog projects to expose the cart and search, respectively, along with any additional configurations the projects may @@ -32,10 +33,14 @@ const AddingMoreMicroFrontends: FC = () => { </Text> <List py="lg"> <List.Item> - The cart can be placed in (path-to-cart-in-header) + The cart can be placed in{" "} + <Code>marketing/src/scenes/Header/components/Search/Search.tsx</Code> </List.Item> <List.Item> - The search can be placed in (path-to-search-in-header) + The search can be placed in{" "} + <Code> + marketing/src/scenes/Header/components/Shortcuts/Shortcuts.tsx + </Code> </List.Item> </List> </ExerciseLayout> diff --git a/packages/workshop/src/scenes/Exercises/components/ConfiguringModuleFederation/ConfiguringModuleFederation.tsx b/packages/workshop/src/scenes/Exercises/components/ConfiguringModuleFederation/ConfiguringModuleFederation.tsx index 27ac84c..b5e809a 100644 --- a/packages/workshop/src/scenes/Exercises/components/ConfiguringModuleFederation/ConfiguringModuleFederation.tsx +++ b/packages/workshop/src/scenes/Exercises/components/ConfiguringModuleFederation/ConfiguringModuleFederation.tsx @@ -1,8 +1,7 @@ import type { FC } from "react"; -import { Alert, Code, Flex, Image, Text } from "@mantine/core"; +import { Accordion, Code, Flex, Image, List, Text, Title } from "@mantine/core"; import { CodeHighlight, CodeHighlightTabs } from "@mantine/code-highlight"; -import { IconInfoCircle } from "@tabler/icons-react"; import ExerciseLayout from "../../shared/components/ExerciseLayout"; @@ -25,6 +24,24 @@ const reactLazy = `const LazilyImported = React.lazy(() => import(...)) <LazilyImported /> </Suspense>`; +const shared = ` + const shared = { + react: { + requiredVersion: "^18.2.0", + singleton: true, + eager: true, + }, + "react-dom": { + requiredVersion: "^18.2.0", + singleton: true, + eager: true, + }, + "react-router-dom": { + requiredVersion: "^6.23.1", + singleton: true, + }, + }`; + const ConfiguringModuleFederation: FC = () => { return ( <ExerciseLayout @@ -33,7 +50,11 @@ const ConfiguringModuleFederation: FC = () => { previous="../set-up" > <Text>Start by checking out this branch</Text> - <CodeHighlight my="lg" lang="sh" code="git checkout exercise-1" /> + <CodeHighlight + my="lg" + lang="sh" + code="git checkout exercise/configuring-module-federation" + /> <Text> Go ahead and do a little bit of poking around to get familiar with the project. Inside packages there are six projects (you can ignore workshop @@ -41,36 +62,64 @@ const ConfiguringModuleFederation: FC = () => { of src contains all the MFEs we will use for our projects. </Text> - <Text pt="md"> + <Title py="xl" order={2}> + Exercise + + Using module federation, pull the Header, Footer, Filter, and - CatalogList into the root of the shell application. Use the image below - as a guide, the layout for the page is provided. + CatalogList into the /shop section of the shell + application. The Header and Footer can be placed in the placeholders + inside shell/src/components/Layout and the Filter and + Catalog in shell/src/scenes/Shop. - - - - + + To accomplish this you'll need to: + + + Create the types for the modules and namespaces for the projects and + MFEs + + + Update the types of the MFEs to be consumed (the Header, the Footer, + the Filter and the Catalog List) + + Expose the MFEs in their respective projects + Consume the MFEs in the shell application + Add any shared modules + + + + The Header and Footer can be found in the marketing project in their + respective scenes. Likewise, the Filter and Catalog in the catalog + project. + + Module Federation can be configured in the{" "} rsbuild.config.ts file + - - The Header and Footer can be found in the marketing project. As a - reminder, you can run a package command using{" "} - {`nx run :`}. The host and the remote - must be running for module federation to work. + Use the image below as a guide, the layout for the page is provided. - } my="xl"> - Quick Tip: For those unfamiliar with React.lazy you must wrap the - components in a Suspense boundary. - - + + + + + + + Running into errors? Did you share the correct modules? + + + + + + ); }; diff --git a/packages/workshop/src/scenes/Exercises/components/FaultTolerance/FaultTolerance.tsx b/packages/workshop/src/scenes/Exercises/components/FaultTolerance/FaultTolerance.tsx index b28c6e5..1cdfb3a 100644 --- a/packages/workshop/src/scenes/Exercises/components/FaultTolerance/FaultTolerance.tsx +++ b/packages/workshop/src/scenes/Exercises/components/FaultTolerance/FaultTolerance.tsx @@ -45,33 +45,29 @@ const FaultTolerance: FC = () => { If the Filter MFE goes down, our customers should still be able to shop - in the catalog, just in a limited capacity. If you want to see it in - action, throw an error in any component in an MFE. + in the catalog, just in a limited capacity. To remedy this, the shell application needs to wrap our MFEs in a - Suspense boundary and an error boundary. Rather than creating an error + suspense boundary and an error boundary. Rather than creating an error boundary from scratch, we will use{" "} react-error-boundary. - - You may continue from your work on Exercise 2, or check out a clean - branch using the command below. - - - - To install react-error-boundary. + + You may continue from your work on the previous exercise, or check out a + clean branch using the command below. - + + To use react-error-boundary. Add error boundaries to each of the MFEs the shell application is - currently using. The fallbacks can be as intricate or plain as you’d + currently using. The fallbacks can be as intricate or plain as you'd like - feel free to explore using Mantine to create more elaborate fallbacks. diff --git a/packages/workshop/src/scenes/Exercises/components/GettingSetup/GettingSetup.tsx b/packages/workshop/src/scenes/Exercises/components/GettingSetup/GettingSetup.tsx index d09cdea..e8597d9 100644 --- a/packages/workshop/src/scenes/Exercises/components/GettingSetup/GettingSetup.tsx +++ b/packages/workshop/src/scenes/Exercises/components/GettingSetup/GettingSetup.tsx @@ -16,10 +16,14 @@ const GettingSetup: FC = () => { - npm & node + + npm & node + - git + + git + @@ -28,19 +32,23 @@ const GettingSetup: FC = () => { The materials for this workshop are in the following GitHub{" "} - Repo. + + Repo + + . - - Once cloned, checkout out the workshop/getting-started{" "} - branch and open the project in your IDE of choice - although this will - be written with vscode in mind - and install the project dependencies. + + Once cloned, checkout out the main branch and open the + project in your IDE of choice - although this will be written with + vscode in mind - and install the project dependencies. Once installed, run the following command. - + - you should see the application opened with a “Hello Attendee!” message. - Once you see the message you can go ahead and kill the dev server. + you should see the application opened with a “Hello - Nice to meet you!” + message. Once you see the message you can go ahead and kill the dev + server. Nx @@ -55,21 +63,25 @@ const GettingSetup: FC = () => { </Text> <CodeHighlight my="lg" code={`nx run <package-name>:<npm-script-name>`} /> <Text> - Try running the dev command in the shell package. Look familiar? (You - should see “Hello Attendee”) + Try running the dev command in the <Code>workshop</Code> package and + navigate the the url. Look familiar? (You should see “Hello - Nice to + meet you!”) </Text> <Text pt="md"> You can also run multiple project commands of the same name using run-many instead of run using the following pattern. </Text> - <CodeHighlight my="lg" code={`nx run-many -t <command>`} /> - <Text>Try running the dev command with run-many</Text> <Alert title="A Quick Note on run-many" icon={<IconInfoCircle />} my="xl"> run-many only runs three processes by default. To run more than three, you can add the parallel flag to run more than that{" "} - {`(--parallel=<number-you-want-to-run>)`} + <Code>{`--parallel=<number-you-want-to-run>`}</Code> </Alert> - <Text>If you got this far, congrats! You're all setup!</Text> + <CodeHighlight my="lg" code={`nx run-many -t <command>`} /> + <Text> + Try running the dev command with run-many and parallel set to 6 + </Text> + + <Text pt="md">If you got this far, congrats! You're all setup!</Text> </ExerciseLayout> ); }; diff --git a/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx index 25ed43b..219af8e 100644 --- a/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx +++ b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx @@ -1,6 +1,7 @@ import type { FC } from "react"; import { Code, List, Text, Title } from "@mantine/core"; +import { CodeHighlight } from "@mantine/code-highlight"; import ExerciseLayout from "../../shared/components/ExerciseLayout"; @@ -11,6 +12,14 @@ const SettingUpRoutes: FC = () => { next="../exercise-6" previous="../exercise-3" > + <Text> + You may continue from your work on the previous exercise, or check out a + clean branch using the command below. + </Text> + <CodeHighlight + my="lg" + code="git checkout soln/adding-more-micro-frontends" + /> <Text> We have several pages left to set up for our application. Let's take a moment to wire up the following MFEs with their respective routes. Each diff --git a/packages/workshop/src/scenes/Exercises/components/SharingCommonModules/SharingCommonModules.tsx b/packages/workshop/src/scenes/Exercises/components/SharingCommonModules/SharingCommonModules.tsx index 797a617..2665150 100644 --- a/packages/workshop/src/scenes/Exercises/components/SharingCommonModules/SharingCommonModules.tsx +++ b/packages/workshop/src/scenes/Exercises/components/SharingCommonModules/SharingCommonModules.tsx @@ -1,10 +1,25 @@ import type { FC } from "react"; -import { Text } from "@mantine/core"; +import { Accordion, Text, Code } from "@mantine/core"; import { CodeHighlight } from "@mantine/code-highlight"; import ExerciseLayout from "../../shared/components/ExerciseLayout"; +const additional = `const addition = { + "@mantine/core": { + requiredVersion: "^7.10.2", + singleton: true, + }, + "@mantine/emotion": { + requiredVersion: "^7.10.2", + singleton: true, + }, + "@tanstack/react-query": { + requiredVersion: "^5.48.0", + singleton: true, + }, +}`; + const SharingCommonModules: FC = () => { return ( <ExerciseLayout @@ -13,10 +28,13 @@ const SharingCommonModules: FC = () => { next="../exercise-3" > <Text> - You may continue from your work on Exercise 1, or check out a clean - branch using the command below. + You may continue from your work on the previous exercise, or check out a + clean branch using the command below. </Text> - <CodeHighlight my="lg" code="git checkout exercise-2" /> + <CodeHighlight + my="lg" + code="git checkout soln/configuring-module-federation" + /> <Text> These applications have some dependencies that are good candidates for sharing via Module Federation. Create a list of libraries you think @@ -28,6 +46,20 @@ const SharingCommonModules: FC = () => { and why you chose the sharing configuration (singleton, eager, etc.) you did for each library. </Text> + <Accordion py="lg"> + <Accordion.Item value="additional"> + <Accordion.Control> + Here are some additional libraries we can share + </Accordion.Control> + <Accordion.Panel> + <CodeHighlight code={additional} /> + </Accordion.Panel> + </Accordion.Item> + </Accordion> + <Text> + Once added go ahead and remove the <Code>TempWrapper</Code>s from the + Header, Footer, Catalog List and Filter + </Text> </ExerciseLayout> ); };