Building a Modular E-commerce Micro-Frontend System
This challenge focuses on designing and implementing a micro-frontend architecture for a small e-commerce platform. You will create a host application that orchestrates multiple independent micro-frontends, each responsible for a distinct feature like product listing, product detail, and shopping cart. This approach promotes team autonomy, independent deployments, and technology diversity.
Problem Description
Your task is to build a simplified e-commerce system using a micro-frontend architecture in React with TypeScript. You will create a Host Application that serves as the main entry point and shell for the entire application. This host will be responsible for loading and displaying different Micro-Frontends dynamically.
You need to implement three micro-frontends:
- Product Listing Micro-Frontend: Displays a list of available products.
- Product Detail Micro-Frontend: Shows detailed information about a specific product.
- Shopping Cart Micro-Frontend: Displays the items currently in the user's cart.
These micro-frontends should be designed to be independently deployable and communicate with the host application and potentially with each other through well-defined interfaces.
Key Requirements:
- Host Application:
- Acts as the main shell.
- Handles routing and determines which micro-frontend to render based on the URL.
- Provides a mechanism for loading micro-frontends.
- Manages shared state or communication channels if necessary (e.g., notifying the cart when a product is added).
- Micro-Frontends (Product Listing, Product Detail, Shopping Cart):
- Each should be a self-contained React application.
- Must expose a specific entry point or render function that the host can call.
- Should communicate with the host or other micro-frontends via defined props or a shared event bus.
- Must be written in TypeScript.
- Communication:
- The Product Listing micro-frontend should be able to trigger the display of the Product Detail micro-frontend, passing the selected product's ID.
- The Product Detail micro-frontend should be able to add an item to the Shopping Cart micro-frontend.
- The Shopping Cart micro-frontend should reflect the items added.
Expected Behavior:
- When the host application is loaded, the Product Listing micro-frontend is displayed.
- Clicking on a product in the listing navigates to a product detail view, rendering the Product Detail micro-frontend.
- From the product detail view, adding a product to the cart updates the Shopping Cart micro-frontend (which should be visible or accessible, e.g., via a persistent header).
- Navigation between these views should be smooth and feel like a single-page application.
Edge Cases to Consider:
- Handling cases where a micro-frontend fails to load.
- Ensuring consistent styling across micro-frontends if they are developed by different teams.
- Managing dependencies – how to avoid version conflicts for shared libraries like React.
Examples
For this challenge, we'll focus on the structural and integration aspects, rather than complex UI interactions. We'll use a simplified data structure for products and cart items.
Conceptual Example (Data Flow):
Input (Initial Host Load): No direct input, the host starts.
Output (Initial Host Load): The Host Application renders the Product Listing Micro-Frontend.
Explanation: The Host Application determines the current route is for product listing and loads the ProductListing component.
Input (User clicks a product in Product Listing):
Let's say the user clicks on a product with id: "prod-123" and name: "Awesome Gadget".
Output (After click):
The Host Application navigates and renders the Product Detail Micro-Frontend, potentially passing prod-123 as a parameter.
Explanation: The Product Listing Micro-Frontend emits an event or calls a host function indicating a product selection. The Host Application intercepts this, updates the URL, and loads the ProductDetail component, passing the product ID.
Input (User clicks "Add to Cart" in Product Detail):
In the ProductDetail view for prod-123, the user clicks "Add to Cart".
Output (After Add to Cart): The Product Detail Micro-Frontend updates the Shopping Cart Micro-Frontend (e.g., by calling a shared service or emitting an event that the cart listens to). The cart now shows "Awesome Gadget".
Explanation: The ProductDetail component communicates the addition of prod-123 to a shared state management mechanism or directly to the ShoppingCart component/service.
Constraints
- Language: TypeScript
- Framework: React
- Micro-Frontend Loading: You can choose any micro-frontend integration strategy. Common approaches include:
- Module Federation: (Recommended for its robust features and support for independent deployments)
- Iframes: (Simpler, but can have UX and communication challenges)
- JavaScript Bundling: (Sharing compiled JS bundles, requires careful dependency management)
- Styling: For this challenge, assume each micro-frontend can manage its own styles, but aim for a consistent visual theme if possible. You don't need to implement complex theming solutions.
- State Management: For communication between micro-frontends, you can use:
- Custom Event Emitters: A simple global event bus.
- Shared Context API (with caution): Can be tricky with independent deployments.
- External State Management Library (e.g., Zustand, Redux): If integrated carefully across micro-frontends.
- Build Tooling: You are free to use any standard React build tools (e.g., Vite, Create React App - though Vite is often preferred for micro-frontend setups). You will need to configure your build tools to support separate builds for the host and micro-frontends.
Notes
- This challenge is about the architecture and integration. Focus on how the pieces fit together.
- You will likely need to set up multiple distinct projects (or sub-projects/workspaces) for your host and each micro-frontend.
- Consider how you will handle routing. Libraries like
react-router-domcan be used, but you'll need to coordinate routing between the host and micro-frontends. - Think about how to expose components or functions from micro-frontends to the host.
- For Module Federation, you will need to configure
webpackorviteplugins accordingly. - Start by getting the basic structure of the Host and one Micro-Frontend communicating, then add the others.
- Success is a working system where the Host loads and orchestrates the defined Micro-Frontends, and basic inter-micro-frontend communication functions as described.