Frontend Architecture Patterns (Micro-Frontends, Jamstack, SSR)
1. Micro-Frontend Architecture (Module Federation, Webpack 5)
| Concept | Technology | Description | Use Case |
|---|---|---|---|
| Module Federation NEW | @module-federation/runtime |
Webpack 5 feature enabling dynamic runtime module sharing across independently deployed applications | Large-scale applications with multiple teams, independent deployments |
| Remote Entry | remoteEntry.js |
Manifest file exposing modules from host application to consumers | Sharing components/utilities between micro-frontends |
| Shared Dependencies | shared: {react, react-dom} |
Single instance of common libraries shared across federated modules to reduce bundle size | Preventing duplicate React instances, reducing memory footprint |
| Host Application | ModuleFederationPlugin |
Container application that consumes remote modules from other micro-frontends | Main shell application orchestrating multiple features |
| Container Strategy | webpack.config.js |
Configuration pattern for exposing and consuming federated modules | Cross-team component sharing, versioning strategy |
Example: Module Federation Configuration
// webpack.config.js - Host Application
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
app2: 'app2@http://localhost:3002/remoteEntry.js'
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' }
}
})
]
};
// webpack.config.js - Remote Application
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
'./Header': './src/components/Header'
},
shared: ['react', 'react-dom']
});
Benefits: Independent deployments, team autonomy, technology agnostic, runtime composition,
incremental upgrades, shared dependencies
2. Component-Based Architecture (React, Vue, Angular)
| Framework | Component Model | Key Features | Architecture Pattern |
|---|---|---|---|
| React | function Component() |
JSX, Virtual DOM, Hooks, Unidirectional data flow, Component composition | UI = f(state) - Functional reactive paradigm |
| Vue 3 | <template><script> |
Composition API, Reactivity system, Single-file components, Template syntax | Progressive framework with reactive data binding |
| Angular | @Component |
TypeScript-first, Dependency injection, RxJS, Decorators, Two-way binding | Full-featured framework with opinionated structure |
| Component Lifecycle | mount/update/unmount |
Predictable lifecycle hooks for initialization, updates, cleanup | Consistent patterns across frameworks |
| Props/Events Pattern | props down, events up |
Parent-to-child data via props, child-to-parent communication via events | Unidirectional data flow maintaining predictability |
React Pattern
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
3. Jamstack Architecture (Static Site Generation, SSG)
| Concept | Implementation | Description | Benefits |
|---|---|---|---|
| Pre-rendering | getStaticProps() |
Generate static HTML at build time from data sources (CMS, APIs, files) | Instant page loads, optimal SEO, reduced server costs |
| Static Site Generator | Next.js, Gatsby, Astro |
Build-time HTML generation with client-side hydration for interactivity | Fast initial load, CDN distribution, security by obscurity |
| Incremental Static Regeneration NEW | revalidate: 60 |
Update static pages after deployment without full rebuild (Next.js) | Fresh content without sacrificing static benefits |
| API Routes | /api/endpoint |
Serverless functions handling dynamic operations (forms, auth, webhooks) | Static frontend with dynamic backend capabilities |
| Headless CMS | Contentful, Strapi |
Content decoupled from presentation, consumed via APIs at build time | Content flexibility, multi-channel distribution |
Example: Next.js Static Site Generation
// pages/blog/[slug].js
export async function getStaticPaths() {
const posts = await fetchAllPosts();
return {
paths: posts.map(post => ({ params: { slug: post.slug } })),
fallback: 'blocking' // ISR for new posts
};
}
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug);
return {
props: { post },
revalidate: 3600 // Regenerate every hour
};
}
export default function BlogPost({ post }) {
return <article>{post.content}</article>;
}
Jamstack Architecture Benefits
- Performance: Pre-rendered HTML served from CDN edge locations
- Security: No database or server vulnerabilities, reduced attack surface
- Scalability: Static files scale infinitely via CDN
- Developer Experience: Modern tooling, Git-based workflows, preview deployments
4. Island Architecture (Astro, Qwik - Partial Hydration)
| Concept | Framework | Description | Performance Impact |
|---|---|---|---|
| Islands Architecture NEW | Astro, Fresh |
Static HTML with interactive "islands" of components that hydrate independently | Minimal JavaScript, selective hydration, faster initial load |
| Partial Hydration | client:load |
Only hydrate components that require interactivity, leave static content as HTML | 90% less JavaScript vs traditional SPA |
| Resumability BETA | Qwik Framework |
Serialize application state on server, resume on client without hydration | Zero JavaScript for static content, instant interactivity |
| Progressive Enhancement | client:visible |
Hydrate components when they enter viewport (lazy hydration) | Faster Time to Interactive (TTI), reduced main thread work |
| Framework Agnostic | React, Vue, Svelte |
Mix different frameworks in same project, each island independent | Use best tool per component, incremental migration |
Example: Astro Islands Architecture
---
// src/pages/index.astro
import Header from '../components/Header.astro';
import ReactCounter from '../components/Counter.jsx';
import VueCarousel from '../components/Carousel.vue';
---
<html>
<body>
<!-- Static HTML, no JS -->
<Header />
<!-- Interactive island, hydrates on load -->
<ReactCounter client:load />
<!-- Lazy hydration when visible -->
<VueCarousel client:visible />
<!-- No hydration, static HTML -->
<footer>Static Footer</footer>
</body>
</html>
5. Server Components (React Server Components, Next.js 13+)
| Concept | Syntax | Description | Benefits |
|---|---|---|---|
| React Server Components NEW | export default async function |
Components that render on server, send HTML to client, never hydrate | Zero JavaScript bundle, direct backend access, streaming |
| Client Components | 'use client' |
Traditional React components with interactivity, hooks, browser APIs | Explicit boundary for client-side JavaScript |
| Async Components | await fetch() |
Server components can be async, directly fetch data without useEffect | Cleaner code, automatic request deduplication |
| Streaming SSR | <Suspense> |
Send HTML progressively as components render, show fallback for slow parts | Faster Time to First Byte (TTFB), progressive enhancement |
| Server Actions BETA | 'use server' |
Functions that run on server, called from client components like RPC | Type-safe server mutations, no API routes needed |
Example: Server Components with Streaming
// app/page.js - Server Component (default)
export default async function Page() {
// Direct database/API access, no client bundle impact
const data = await db.query('SELECT * FROM posts');
return (
<main>
<h1>Posts</h1>
<Suspense fallback={<Loading />}>
<PostList data={data} />
</Suspense>
</main>
);
}
// components/InteractiveButton.js - Client Component
'use client';
import { useState } from 'react';
export default function InteractiveButton() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
// Server Action
async function createPost(formData) {
'use server';
const title = formData.get('title');
await db.insert({ title });
revalidatePath('/posts');
}
Important: Server Components cannot use browser APIs, hooks (useState, useEffect), or event
handlers. Use
'use client' directive for interactive components.
6. Edge-First Architecture (Edge Runtime, Vercel, Cloudflare)
| Concept | Platform | Description | Use Case |
|---|---|---|---|
| Edge Functions | Vercel, Cloudflare Workers |
Lightweight serverless functions running at CDN edge locations globally | Low-latency API responses, personalization, A/B testing |
| Edge Middleware | middleware.js |
Intercept requests before they reach application, run logic at edge | Authentication, redirects, geolocation, feature flags |
| Edge Runtime | export const runtime = 'edge' |
Subset of Node.js APIs, optimized for fast cold starts (<10ms) | Dynamic rendering near users, streaming responses |
| Incremental Static Regeneration | revalidate |
Static pages regenerate at edge on-demand, cached globally | E-commerce, content sites with frequent updates |
| Edge Config | @vercel/edge-config |
Ultra-fast key-value store accessible from edge functions (<1ms reads) | Feature flags, A/B test configs, redirects |
Example: Next.js Edge Middleware
// middleware.js - Runs at edge for all routes
import { NextResponse } from 'next/server';
export function middleware(request) {
// Geolocation-based redirect
const country = request.geo?.country;
if (country === 'US') {
return NextResponse.redirect(new URL('/us', request.url));
}
// A/B testing
const bucket = Math.random() < 0.5 ? 'a' : 'b';
const response = NextResponse.next();
response.cookies.set('bucket', bucket);
// Authentication check
const token = request.cookies.get('session');
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return response;
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
};
Performance Benefit: Edge-first architecture reduces latency by 50-90% compared to traditional
origin servers by serving content from locations close to users.