Designing a Micro Frontend Application
Project Architecture Planning
Layered Architecture Design
Micro Frontend Architecture Layers:
1. Infrastructure Layer
- Micro Frontend Framework (e.g., Module Federation)
- Shared Dependency Management
- Environment Configuration
2. Communication Layer
- Event Bus
- State Management
- API Gateway Integration
3. Application Layer
- Sub - Application 1 (User Management)
- Sub - Application 2 (Order Management)
- Sub - Application 3 (Product Display)
4. Presentation Layer
- Main Application Shell
- Layout Components
- Global UI Components
Technology Selection Matrix
Component Recommended Technology Alternative Options Micro Frontend Framework Module Federation (qiankun) Single-SPA State Management Redux (Zustand) MobX (Jotai) Communication Mechanism Custom Events/Redux RxJS Build Tool Webpack (Vite) Rollup Type Checking TypeScript Flow
Directory Structure Example
micro - frontend /
├── apps / # Sub - application directory
│ ├── user - service / # User management sub - application
│ ├── order - service / # Order management sub - application
│ └── product - service / # Product display sub - application
├── shell / # Main application shell
│ ├── src /
│ │ ├── app - shell / # Shell application core
│ │ ├── layouts / # Global layouts
│ │ └── shared / # Shared components
├── shared / # Shared resources
│ ├── components / # Shared UI components
│ ├── utils / # Utility functions
│ └── hooks / # Custom hooks
└── config / # Configuration files
├── webpack.config.js # Main application configuration
└── mf - config.js # Micro frontend configuration
Sub-Application Decomposition and Integration
Decomposition Principles
Business Domain Boundaries : Divide by business domains (e.g., user, order, product)
Team Structure Alignment : Each sub-application corresponds to an independent team
Technology Stack Consistency : Maintain uniform tech stack within a sub-application
Independent Deployment Capability : Each sub-application can be built and deployed independently
Integration Strategy
// Main application integration example (Module Federation)
const { ModuleFederationPlugin } = require ( ' webpack ' ).container;
module . exports = {
plugins : [
new ModuleFederationPlugin ({
name : ' mainApp ' ,
remotes : {
userService : ' userService@http://localhost:3001/remoteEntry.js ' ,
orderService : ' orderService@http://localhost:3002/remoteEntry.js ' ,
},
shared : {
react : { singleton : true , requiredVersion : ' ^18.2.0 ' },
' react-dom ' : { singleton : true , requiredVersion : ' ^18.2.0 ' },
},
}),
],
};
Dynamic Loading Implementation
// Dynamically load sub-application
async function loadMicroApp ( appName ) {
const container = document. getElementById ( `app- ${ appName } ` );
const { getModule } = await import (
/* webpackIgnore: true */
`http://localhost:300 ${ appName === ' userService ' ? ' 1 ' : ' 2 ' } /remoteEntry.js`
);
const module = await getModule (appName);
const App = module .default;
ReactDOM. render (< App />, container);
}
Communication and State Design
Communication Mode Selection
Scenario Recommended Approach Implementation Example Parent-Child Communication Props/Callbacks <Child onEvent={handler} />Sibling Communication Event Bus eventBus.emit('event', data)Cross-Level Communication State Management dispatch({ type: 'ACTION' })Global State Shared Redux useSelector(state => state.user)
State Management Approach
// Redux shared state example
// store.js
import { configureStore } from ' @reduxjs/toolkit ' ;
import userReducer from ' ./userSlice ' ;
import cartReducer from ' ./cartSlice ' ;
export const store = configureStore ({
reducer : {
user : userReducer,
cart : cartReducer,
},
});
// Sub-application integration
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
export const { store : qiankunStore } = await import ( ' ./store ' );
export function initGlobalState ( state ) {
if (qiankunStore) {
qiankunStore. dispatch ({ type : ' INIT ' , payload : state });
}
}
}
State Synchronization Strategies
Unidirectional Data Flow : Main app → Sub-app (via props)
Event-Driven : Sub-app → Main app (via event bus)
State Hoisting : Elevate shared state to main application
Change Notification : Publish events on state changes
Loading and Rendering Optimization
Code Splitting Strategy
// Webpack dynamic import
const HeavyComponent = React. lazy (() => import ( ' ./HeavyComponent ' ));
function App () {
return (
< React.Suspense fallback ={ < div >Loading...</ div > } >
< HeavyComponent />
</ React.Suspense >
);
}
Preloading Techniques
<!-- Preload critical resources -->
< link rel = " preload " href = " critical.css " as = " style " >
< link rel = " preload " href = " main.js " as = " script " >
< link rel = " prefetch " href = " optional.js " as = " script " >
Rendering Optimization
// Virtual list implementation
function VirtualList ({ items , itemHeight , containerHeight }) {
const [scrollTop, setScrollTop] = useState ( 0 );
const visibleCount = Math. ceil (containerHeight / itemHeight);
const startIndex = Math. floor (scrollTop / itemHeight);
const visibleItems = items. slice (startIndex, startIndex + visibleCount);
return (
< div style ={ { height : containerHeight, overflowY : ' auto ' } } >
< div style ={ { height : items.length * itemHeight, position : ' relative ' } } >
{ visibleItems. map (( item , index ) => (
< div
key ={ startIndex + index }
style ={ {
position : ' absolute ' ,
top : (startIndex + index) * itemHeight,
width : ' 100% '
} }
>
{ item }
</ div >
)) }
</ div >
</ div >
);
}
Data Management and Synchronization
State Synchronization Approach
// State synchronization using Redux
const store = configureStore ({
reducer : {
user : userReducer,
cart : cartReducer,
},
});
// Sub-application integration
if (window.__POWERED_BY_QIANKUN__) {
store. subscribe (() => {
// Notify sub-applications on state changes
window. postMessage ({
type : ' STATE_UPDATE ' ,
payload : store. getState (),
}, ' * ' );
});
}
Data Caching Strategy
// Data caching using SWR
import useSWR from ' swr ' ;
function UserProfile () {
const { data, error } = useSWR ( ' /api/user ' , fetcher, {
revalidateOnFocus : false ,
dedupingInterval : 5000 ,
});
if (error) return < div >Error loading user</ div >;
if ( ! data) return < div >Loading...</ div >;
return < div > { data.name } </ div >;
}
Key Metrics Monitoring
// Performance metrics collection
const performanceMetrics = {
tbt : performance.metrics.totalBlockingTime,
fid : performance. getEntriesByName ( ' first-input ' )[ 0 ]?.processingStart,
cls : performance.metrics.layoutShift.total,
lcp : performance. getEntriesByType ( ' largest-contentful-paint ' )[ 0 ]?.startTime,
};
// Send to monitoring system
trackPerformance (performanceMetrics);
Lighthouse : Comprehensive performance assessment
WebPageTest : Multi-location testing
Chrome DevTools : Detailed performance analysis
React Profiler : Component-level performance analysis
Micro Frontend Deployment and Optimization
CI/CD Pipeline Implementation
Pipeline Configuration Example (GitHub Actions)
name: CI/CD Pipeline
on:
push:
branches: [ main ]
jobs :
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: ' 16 '
- name: Install dependencies
run: npm ci
- name: Build applications
run: |
npm run build:shell
npm run build:user-service
npm run build:order-service
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dist
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v2
with:
name: dist
- name: Deploy to production
run: |
scp -r dist user@server:/var/www/micro-frontend
ssh user@server " cd /var/www/micro-frontend && npm install --production && pm2 restart all "
Automated Testing and Release
Testing Strategy
// Jest unit test example
describe ( ' User Service ' , () => {
it ( ' should fetch user data ' , async () => {
const response = await fetchUserData ( 1 );
expect (response). toHaveProperty ( ' id ' , 1 );
});
});
// Cypress E2E test example
describe ( ' Microfrontend App ' , () => {
beforeEach (() => {
cy. visit ( ' / ' );
});
it ( ' loads all microfrontends ' , () => {
cy. get ( ' [data-testid="user-service"] ' ). should ( ' exist ' );
cy. get ( ' [data-testid="order-service"] ' ). should ( ' exist ' );
});
});
Automated Release Process
Code Review : PR → Code Review → Merge
Build : CI → Build all applications
Testing : Automated tests → Manual review
Staging : Validation in staging environment
Production Release : Blue-green deployment/Canary release
Security and Operations Practices
Security Hardening Measures
CSP Strategy :
< meta http-equiv = " Content-Security-Policy " content = "
default-src 'self';
script-src 'self' https://cdn.example.com 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
" >
XSS Protection :
// Sanitize HTML using DOMPurify
import DOMPurify from ' dompurify ' ;
function SafeHtml ({ html }) {
const clean = DOMPurify. sanitize (html);
return < div dangerouslySetInnerHTML ={ { __html : clean } } />;
}
Operations Monitoring
Log Aggregation : ELK Stack
Performance Monitoring : Prometheus + Grafana
Error Tracking : Sentry
Health Checks :
// Health check endpoint
app. get ( ' /health ' , ( req , res ) => {
res. json ({
status : ' UP ' ,
uptime : process. uptime (),
timestamp : new Date (),
});
});
High-Availability Deployment
Load Balancing : Nginx configuration example
upstream micro_frontend {
server app1.example.com;
server app2.example.com;
server app3.example.com;
}
server {
listen 80 ;
location / {
proxy_pass http: //micro_frontend;
proxy_set_header Host $host;
}
}
Auto-Scaling : Kubernetes HPA configuration
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: micro-frontend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: micro-frontend
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type : Utilization
averageUtilization: 70
Summary and Recommendations
Architecture Design Principles :
Follow single responsibility principle for sub-application decomposition
Establish clear communication and state management mechanisms
Use progressive loading strategies to optimize performance
Performance Optimization Focus :
Implement code splitting and lazy loading
Preload critical resources
Use virtual lists for large dataset rendering
Deployment Strategy Recommendations :
Implement blue-green or canary releases
Build comprehensive monitoring systems
Automate testing for critical paths
Security Practices :
Enforce CSP strategies
Sanitize user inputs
Conduct regular security audits
Team Collaboration Recommendations :
Establish cross-team communication mechanisms
Define unified development standards
Conduct regular technical sharing and knowledge transfer
Implementing a micro frontend architecture is an ongoing optimization process that requires continuous adjustments based on business needs and technological advancements. Start with pilot projects to build experience before scaling organization-wide. Establish continuous feedback loops to regularly evaluate architecture effectiveness and make iterative improvements.