<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dimuthu Abeysinghe</title>
    <description>The latest articles on Forem by Dimuthu Abeysinghe (@dimuthu7).</description>
    <link>https://forem.com/dimuthu7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F954465%2F5136723e-e1c4-409f-b3c6-a7fceb6a8a63.jpeg</url>
      <title>Forem: Dimuthu Abeysinghe</title>
      <link>https://forem.com/dimuthu7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dimuthu7"/>
    <language>en</language>
    <item>
      <title>Building Micro Frontends with React, Vite, and Module Federation: A Complete Guide</title>
      <dc:creator>Dimuthu Abeysinghe</dc:creator>
      <pubDate>Thu, 18 Dec 2025 07:46:57 +0000</pubDate>
      <link>https://forem.com/dimuthu7/building-micro-frontends-with-react-vite-and-module-federation-a-complete-guide-4k</link>
      <guid>https://forem.com/dimuthu7/building-micro-frontends-with-react-vite-and-module-federation-a-complete-guide-4k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🔗 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/Dimuthu7/Micro-frontend-with-React-Vite" rel="noopener noreferrer"&gt;https://github.com/Dimuthu7/Micro-frontend-with-React-Vite&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A comprehensive guide to building production-ready micro frontends architecture using React, TypeScript, Vite, and Module Federation. Learn how to break down monolithic frontends into independent, scalable applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to Micro Frontends&lt;/li&gt;
&lt;li&gt;Why Micro Frontends?&lt;/li&gt;
&lt;li&gt;Benefits of Micro Frontends Architecture&lt;/li&gt;
&lt;li&gt;Project Overview&lt;/li&gt;
&lt;li&gt;Tech Stack&lt;/li&gt;
&lt;li&gt;Understanding Module Federation&lt;/li&gt;
&lt;li&gt;Architecture Deep Dive&lt;/li&gt;
&lt;li&gt;Implementation Details&lt;/li&gt;
&lt;li&gt;Local Development Setup&lt;/li&gt;
&lt;li&gt;Docker Setup and Deployment&lt;/li&gt;
&lt;li&gt;Running the Project&lt;/li&gt;
&lt;li&gt;Best Practices Implemented&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Introduction to Micro Frontends
&lt;/h2&gt;

&lt;p&gt;Micro Frontends is an architectural approach that extends the microservices pattern to the frontend. Instead of building a monolithic frontend application, you break it down into smaller, independent applications that can be developed, tested, and deployed separately.&lt;/p&gt;

&lt;p&gt;Think of it like a restaurant: instead of one chef preparing everything, you have specialized chefs (teams) working on different dishes (features) that come together to create a complete meal (user experience).&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Micro Frontends?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem with Monolithic Frontends
&lt;/h3&gt;

&lt;p&gt;As applications grow, monolithic frontends face several challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scaling Issues&lt;/strong&gt;: Large codebases become difficult to navigate and maintain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Bottlenecks&lt;/strong&gt;: One bug can block the entire release&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team Coordination&lt;/strong&gt;: Multiple teams working on the same codebase creates conflicts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology Lock-in&lt;/strong&gt;: Difficult to adopt new technologies or upgrade dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Large bundles slow down initial page load&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Benefits of Micro Frontends Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Team Autonomy &amp;amp; Scalability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Independent Development&lt;/strong&gt;: Teams can work in parallel without stepping on each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Own Technology Stack&lt;/strong&gt;: Each team can choose frameworks that best fit their needs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster Feature Delivery&lt;/strong&gt;: Smaller codebases mean faster development cycles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Coordination&lt;/strong&gt;: Less need for cross-team meetings and synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Independent Deployment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolated Releases&lt;/strong&gt;: Deploy features independently without affecting other parts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster Rollouts&lt;/strong&gt;: Release features as soon as they're ready&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safer Rollbacks&lt;/strong&gt;: Rollback individual features without impacting the entire app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B Testing&lt;/strong&gt;: Easier to test new features with a subset of users&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Technology Diversity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework Flexibility&lt;/strong&gt;: Use React for one feature, Vue for another, Angular for a third&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradual Migration&lt;/strong&gt;: Migrate legacy code piece by piece&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology Experimentation&lt;/strong&gt;: Try new technologies without rewriting everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent Upgrades&lt;/strong&gt;: Upgrade dependencies per micro frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Code Isolation &amp;amp; Maintainability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smaller Codebases&lt;/strong&gt;: Easier to understand, test, and maintain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear Boundaries&lt;/strong&gt;: Well-defined interfaces prevent tight coupling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier Onboarding&lt;/strong&gt;: New developers can focus on one micro frontend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Organization&lt;/strong&gt;: Clear separation of concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Performance Optimization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Splitting&lt;/strong&gt;: Load only what's needed, when it's needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent Caching&lt;/strong&gt;: Each micro frontend can have its own caching strategy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller Bundles&lt;/strong&gt;: Smaller applications mean smaller bundle sizes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt;: Load components on-demand for better performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Fault Isolation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error Containment&lt;/strong&gt;: Errors in one micro frontend don't crash the entire app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Degradation&lt;/strong&gt;: Error boundaries can handle failures elegantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Resilience&lt;/strong&gt;: One failing feature doesn't break the user experience&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;This project demonstrates a production-ready micro frontends architecture using a &lt;strong&gt;Product Catalog&lt;/strong&gt; application. The application consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host Application&lt;/strong&gt;: The container/orchestrator that displays the product catalog and manages application state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote Application&lt;/strong&gt;: A micro frontend that provides detailed product information components&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── host/ # Container application (Host)
│ ├── src/
│ │ ├── components/
│ │ │ ├── Header.tsx # Application header with cart
│ │ │ ├── Footer.tsx # Application footer
│ │ │ ├── ProductList.tsx # Product grid component
│ │ │ ├── ProductListView.tsx # Product list view with header
│ │ │ ├── ProductDetailsView.tsx # Product details view container
│ │ │ ├── BackButton.tsx # Reusable back navigation button
│ │ │ └── ErrorBoundary.tsx # Error boundary for graceful error handling
│ │ ├── data/
│ │ │ └── products.ts # Product data
│ │ ├── types/
│ │ │ └── index.ts # TypeScript type definitions
│ │ └── App.tsx # Main application (orchestrator)
│ ├── Dockerfile
│ └── nginx.conf
├── remote/ # Micro frontend application (Remote)
│ ├── src/
│ │ ├── components/
│ │ │ └── ProductCard.tsx # Remote component (exposed via Module Federation)
│ │ └── types/
│ │ └── index.ts # TypeScript type definitions
│ ├── Dockerfile
│ └── nginx.conf
├── docker-compose.yml # Docker orchestration
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Technologies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 18&lt;/strong&gt;: Modern UI library with hooks and Suspense for async operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript 5&lt;/strong&gt;: Type-safe development with compile-time error checking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite 5&lt;/strong&gt;: Fast build tool and dev server with excellent HMR (Hot Module Replacement)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS 3&lt;/strong&gt;: Utility-first CSS framework for rapid UI development&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Micro Frontends Technology
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Module Federation&lt;/strong&gt;: Runtime module sharing and dynamic loading&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@originjs/vite-plugin-federation&lt;/strong&gt;: Vite plugin that enables Module Federation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DevOps &amp;amp; Infrastructure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker &amp;amp; Docker Compose&lt;/strong&gt;: Containerization for consistent environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt;: Production web server with optimized configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 18+&lt;/strong&gt;: JavaScript runtime environment&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Understanding Module Federation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Module Federation?
&lt;/h3&gt;

&lt;p&gt;Module Federation is a JavaScript architecture that allows a JavaScript application to dynamically load code from another application at runtime. It was introduced by Webpack 5 and has been adapted for Vite through plugins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Concepts
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Host Application (Container)
&lt;/h4&gt;

&lt;p&gt;The host application is the main application that consumes remote modules. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loads and orchestrates remote components&lt;/li&gt;
&lt;li&gt;Manages application state&lt;/li&gt;
&lt;li&gt;Handles routing and navigation&lt;/li&gt;
&lt;li&gt;Provides the shell/framework for the application&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Remote Application (Micro Frontend)
&lt;/h4&gt;

&lt;p&gt;The remote application exposes modules that can be consumed by the host. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposes components, utilities, or features&lt;/li&gt;
&lt;li&gt;Can run independently&lt;/li&gt;
&lt;li&gt;Shares dependencies with the host to avoid duplication&lt;/li&gt;
&lt;li&gt;Maintains its own build and deployment pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Shared Dependencies
&lt;/h4&gt;

&lt;p&gt;Both host and remote can share common dependencies (like React, React-DOM) to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid loading duplicate code&lt;/li&gt;
&lt;li&gt;Ensure consistent versions&lt;/li&gt;
&lt;li&gt;Reduce bundle sizes&lt;/li&gt;
&lt;li&gt;Maintain singleton instances&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Module Federation Works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                  Browser (Client)                       │
│                                                         │
│ 1. User visits Host App (localhost:5173)                │
│ 2. Host App loads and initializes                       │
│ 3. User clicks on a product                             │
│ 4. Host App requests Remote Component                   │
│                                                         │
│ ┌─────────────┐                ┌─────────────┐          │
│ │ Host App    │                │ Remote App  │          │
│ │ (Port 5173) │──────────────▶ │ (Port 5174) │          │
│ │             │ HTTP Request   │             │          │
│ │             │◀────────────── │             │          │
│ │             │ remoteEntry.js │             │          │
│ │             │ + ProductCard  │             │          │
│ └─────────────┘                └─────────────┘          │
│                                                         │
│ 5. Module Federation loads remote component dynamically │
│ 6. Component renders in Host App context                │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Architecture Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Component Architecture
&lt;/h3&gt;

&lt;p&gt;The host application follows a clean component-based architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App.tsx (Orchestrator)
├── Header (Cart display)
├── ProductListView (Product catalog)
│   └── ProductList (Product grid)
└── ProductDetailsView (Remote component container)
    └── RemoteProductCard (Loaded from remote app)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────┐         Props          ┌─────────────┐
│ Host App   │───────────────────────▶│ Remote App  │
│            │                        │             │
│ - State    │◀───────────────────────│ - Component │
│ - Handlers │        Callbacks       │ - UI        │
└────────────┘                        └─────────────┘
      │                                      │
      │    Shared React Instance             │
      └──────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Complete Request Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initial Page Load&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser requests the host app&lt;/li&gt;
&lt;li&gt;Nginx serves &lt;code&gt;index.html&lt;/code&gt; and host app bundle&lt;/li&gt;
&lt;li&gt;React app initializes and renders &lt;code&gt;ProductListView&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Product catalog displays&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Clicks Product&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host app updates state with selected product&lt;/li&gt;
&lt;li&gt;Switches to &lt;code&gt;ProductDetailsView&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Component lazy loads the remote component&lt;/li&gt;
&lt;li&gt;Module Federation makes HTTP request to remote app&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remote Component Loading&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host requests &lt;code&gt;remoteEntry.js&lt;/code&gt; from remote app&lt;/li&gt;
&lt;li&gt;Remote app serves Module Federation manifest&lt;/li&gt;
&lt;li&gt;Host requests component bundle (&lt;code&gt;ProductCard.[hash].js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Module Federation runtime loads and executes component&lt;/li&gt;
&lt;li&gt;Component renders in host context with shared React instance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Interaction&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User clicks "Add to Cart" in remote component&lt;/li&gt;
&lt;li&gt;Callback function executes in host app&lt;/li&gt;
&lt;li&gt;Host app updates cart count state&lt;/li&gt;
&lt;li&gt;Header re-renders with new count&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Implementation Details
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Module Federation Configuration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Host Application (host/vite.config.ts)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    react(),
    federation({
      name: 'host_app',
      remotes: {
        remote_app: {
          external: `http://${process.env.VITE_REMOTE_HOST || 'localhost'}:${process.env.VITE_REMOTE_PORT || '5174'}/assets/remoteEntry.js`,
          shareScope: 'default',
        },
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
      },
    }),
  ],
  build: {
    modulePreload: false,
    target: 'esnext',
    minify: false,
    cssCodeSplit: false,
  },
  server: {
    port: Number(process.env.PORT) || 5173,
    host: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;remotes&lt;/code&gt;: Defines where to load remote modules from&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shared&lt;/code&gt;: Specifies dependencies to share (React, React-DOM)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;singleton: true&lt;/code&gt;: Ensures only one instance of React is loaded&lt;/li&gt;
&lt;li&gt;Environment variables allow different URLs for different environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Remote Application (remote/vite.config.ts)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    react(),
    federation({
      name: 'remote_app',
      filename: 'remoteEntry.js',
      exposes: {
        './ProductCard': './src/components/ProductCard',
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
      },
    }),
  ],
  build: {
    modulePreload: false,
    target: 'esnext',
    minify: false,
    cssCodeSplit: false,
  },
  server: {
    port: Number(process.env.PORT) || 5174,
    host: true,
    cors: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;exposes&lt;/code&gt;: Defines which modules/components to expose&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filename&lt;/code&gt;: Name of the Module Federation manifest file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shared&lt;/code&gt;: Same shared dependencies as host to avoid duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Loading Remote Components
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ProductDetailsView Component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Suspense, lazy } from 'react';
import { ErrorBoundary } from './ErrorBoundary';

// Lazy load the remote ProductCard component
const RemoteProductCard = lazy(() =&amp;gt; import('remote_app/ProductCard'));

interface ProductDetailsViewProps {
  product: Product;
  onAddToCart: () =&amp;gt; void;
  onClose: () =&amp;gt; void;
}

export const ProductDetailsView: React.FC&amp;lt;ProductDetailsViewProps&amp;gt; = ({
  product,
  onAddToCart,
  onClose,
}) =&amp;gt; {
  return (
    &amp;lt;ErrorBoundary
      fallback={
        &amp;lt;div&amp;gt;Failed to load remote component&amp;lt;/div&amp;gt;
      }
    &amp;gt;
      &amp;lt;Suspense
        fallback={
          &amp;lt;div&amp;gt;Loading product details...&amp;lt;/div&amp;gt;
        }
      &amp;gt;
        &amp;lt;RemoteProductCard 
          product={product} 
          onAddToCart={onAddToCart} 
        /&amp;gt;
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/ErrorBoundary&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt;: Uses React's &lt;code&gt;lazy()&lt;/code&gt; to dynamically import the remote component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suspense&lt;/strong&gt;: Provides loading state while component is being fetched&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Boundary&lt;/strong&gt;: Gracefully handles errors if remote component fails to load&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Safety&lt;/strong&gt;: TypeScript ensures props match the expected interface&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Error Handling
&lt;/h3&gt;

&lt;p&gt;The project implements a robust error boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, ErrorInfo, ReactNode } from 'react';

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
}

interface State {
  hasError: boolean;
  error?: Error;
}

export class ErrorBoundary extends Component&amp;lt;Props, State&amp;gt; {
  public state: State = {
    hasError: false,
  };

  public static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error };
  }

  public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error('ErrorBoundary caught an error:', error, errorInfo);
  }

  public render() {
    if (this.state.hasError) {
      return this.props.fallback || &amp;lt;DefaultErrorUI /&amp;gt;;
    }
    return this.props.children;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that if the remote component fails to load, the application doesn't crash and shows a user-friendly error message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type Safety Across Applications
&lt;/h3&gt;

&lt;p&gt;Both applications share the same TypeScript interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// host/src/types/index.ts
// remote/src/types/index.ts
export interface Product {
  id: string;
  name: string;
  description: string;
  price: number;
  image: string;
  category: string;
  inStock: boolean;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures type safety when passing data between host and remote applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Local Development Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 18+&lt;/strong&gt; and npm/yarn/pnpm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Editor&lt;/strong&gt; (VS Code recommended)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt; (for cloning the repository)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-Step Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Install Dependencies
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Install Remote App Dependencies:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd remote
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Install Host App Dependencies:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ../host
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the Makefile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Understanding the Setup
&lt;/h4&gt;

&lt;p&gt;The applications need to run simultaneously because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The host app needs to fetch the remote component from the remote app&lt;/li&gt;
&lt;li&gt;Both apps need to be running for Module Federation to work&lt;/li&gt;
&lt;li&gt;The remote app must be accessible via HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Running the Applications
&lt;/h4&gt;

&lt;p&gt;You need &lt;strong&gt;two terminal windows&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal 1 - Remote App (must start first):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd remote
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The remote app will run on &lt;code&gt;http://localhost:5174&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal 2 - Host App:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd host
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The host app will run on &lt;code&gt;http://localhost:5173&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Verify the Setup
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open your browser and navigate to &lt;code&gt;http://localhost:5173&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You should see the product catalog&lt;/li&gt;
&lt;li&gt;Click on any product&lt;/li&gt;
&lt;li&gt;The product details should load from the remote micro frontend&lt;/li&gt;
&lt;li&gt;Check the browser console for any errors&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;p&gt;You can customize the setup using environment variables:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Host App&lt;/strong&gt; (&lt;code&gt;.env&lt;/code&gt; file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PORT=5173
VITE_REMOTE_HOST=localhost
VITE_REMOTE_PORT=5174
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remote App&lt;/strong&gt; (&lt;code&gt;.env&lt;/code&gt; file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PORT=5174
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Troubleshooting Local Setup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Issue: Remote component not loading&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the remote app is running before starting the host app&lt;/li&gt;
&lt;li&gt;Check that both apps are running on the correct ports&lt;/li&gt;
&lt;li&gt;Verify the remote URL in &lt;code&gt;host/vite.config.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check browser console for CORS errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Issue: CORS errors&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The remote app's Vite dev server has CORS enabled&lt;/li&gt;
&lt;li&gt;Ensure both apps are running&lt;/li&gt;
&lt;li&gt;Check that ports match the configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Issue: Type errors&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;npm run build&lt;/code&gt; to check for TypeScript errors&lt;/li&gt;
&lt;li&gt;Ensure both apps have the same type definitions&lt;/li&gt;
&lt;li&gt;Check that shared types are synchronized&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Docker Setup and Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Docker?
&lt;/h3&gt;

&lt;p&gt;Docker provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Environments&lt;/strong&gt;: Same environment in development and production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Deployment&lt;/strong&gt;: Package everything needed to run the application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt;: Each application runs in its own container&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration&lt;/strong&gt;: Docker Compose manages multiple containers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│         Docker Network (microfrontends-network)         │
│                                                         │
│  ┌──────────────┐               ┌──────────────┐        │
│  │  host-app    │               │ remote-app   │        │
│  │  :5173       │──────────────▶│ :5174        │        │
│  │  (Nginx)     │  HTTP Request │ (Nginx)      │        │
│  │              │◀──────────────│              │        │
│  │              │  remoteEntry  │              │        │
│  └──────────────┘               └──────────────┘        │
│                                                         │
│  Both containers communicate via service names          │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dockerfile Structure
&lt;/h3&gt;

&lt;p&gt;Both applications use multi-stage builds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1: Builder&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci

# Copy source code
COPY . .

# Build the application
RUN npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stage 2: Production&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM nginx:alpine

# Install wget for health checks
RUN apk add --no-cache wget

# Copy built assets from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Expose port
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits of Multi-Stage Builds:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller final image (only production files)&lt;/li&gt;
&lt;li&gt;Faster builds (cached layers)&lt;/li&gt;
&lt;li&gt;Security (no build tools in production image)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker Compose Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  remote-app:
    build:
      context: ./remote
      dockerfile: Dockerfile
    container_name: micro-frontend-remote
    ports:
      - "5174:80"
    networks:
      - micro-frontend-network
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/assets/remoteEntry.js"]
      interval: 10s
      timeout: 5s
      retries: 5

  host-app:
    build:
      context: ./host
      dockerfile: Dockerfile
      args:
        - VITE_REMOTE_HOST=remote-app
        - VITE_REMOTE_PORT=80
    container_name: micro-frontend-host
    ports:
      - "5173:80"
    depends_on:
      remote-app:
        condition: service_healthy
    networks:
      - micro-frontend-network

networks:
  micro-frontend-network:
    driver: bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Health Checks&lt;/strong&gt;: Ensures remote app is ready before starting host app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Names&lt;/strong&gt;: Containers communicate using service names (&lt;code&gt;remote-app&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Isolation&lt;/strong&gt;: Both apps on the same Docker network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port Mapping&lt;/strong&gt;: Exposes apps on host machine ports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Nginx Configuration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why Nginx?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Production Web Server&lt;/strong&gt;: More performant than development servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS Headers&lt;/strong&gt;: Required for Module Federation cross-origin requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SPA Routing&lt;/strong&gt;: Handles client-side routing correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Gzip compression, caching, security headers&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Remote App Nginx Config
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    root /usr/share/nginx/html;

    # CORS headers for Module Federation
    location = /assets/remoteEntry.js {
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # CORS for JavaScript files
    location ~* ^/assets/.*\.js$ {
        add_header Access-Control-Allow-Origin * always;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # SPA routing
    location / {
        try_files $uri $uri/ /index.html;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CORS Headers&lt;/strong&gt;: Essential for cross-origin Module Federation requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Cache for remoteEntry.js&lt;/strong&gt;: Ensures latest version is always loaded&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache for Assets&lt;/strong&gt;: Optimizes performance with long-term caching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SPA Routing&lt;/strong&gt;: Serves &lt;code&gt;index.html&lt;/code&gt; for all routes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Running the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Docker (Recommended for Production)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start Both Applications:
&lt;code&gt;docker-compose up --build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Start in Detached Mode:
&lt;code&gt;docker-compose up -d --build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;View Logs:
&lt;code&gt;docker-compose logs -f&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stop Applications:
&lt;code&gt;docker-compose down&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using Makefile:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make docker-up              # Start with logs
make docker-up-detached     # Start in background
make docker-down            # Stop containers
make docker-logs            # View logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Access Applications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host App&lt;/strong&gt;: &lt;a href="http://localhost:5173" rel="noopener noreferrer"&gt;http://localhost:5173&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote App&lt;/strong&gt;: &lt;a href="http://localhost:5174" rel="noopener noreferrer"&gt;http://localhost:5174&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Option 2: Local Development
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Using Makefile:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make install    # Install dependencies
make dev        # Instructions for running both apps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Manual:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal 1
cd remote
npm run dev

# Terminal 2
cd host
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 3: Production Build
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Build Both Applications:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;make build&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or manually:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build remote app first
cd remote
npm run build

# Build host app
cd ../host
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Preview Production Build:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal 1
cd remote
npm run preview

# Terminal 2
cd host
npm run preview---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices Implemented
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Component Architecture
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Clean separation of concerns&lt;/li&gt;
&lt;li&gt;Focused, reusable components&lt;/li&gt;
&lt;li&gt;Clear component hierarchy&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Error Handling
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Error boundaries for remote components&lt;/li&gt;
&lt;li&gt;Fallback UI for failed loads&lt;/li&gt;
&lt;li&gt;User-friendly error messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Performance Optimization
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Lazy loading with React Suspense&lt;/li&gt;
&lt;li&gt;Code splitting per micro frontend&lt;/li&gt;
&lt;li&gt;Shared dependencies to reduce bundle size&lt;/li&gt;
&lt;li&gt;Nginx caching strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Type Safety
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Shared TypeScript types across applications&lt;/li&gt;
&lt;li&gt;Type-safe component props&lt;/li&gt;
&lt;li&gt;Compile-time error checking&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. Development Experience
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Hot Module Replacement (HMR) in development&lt;/li&gt;
&lt;li&gt;Clear project structure&lt;/li&gt;
&lt;li&gt;Environment variable configuration&lt;/li&gt;
&lt;li&gt;Makefile for common tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Production Readiness
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Multi-stage Docker builds&lt;/li&gt;
&lt;li&gt;Health checks for orchestration&lt;/li&gt;
&lt;li&gt;Security headers in Nginx&lt;/li&gt;
&lt;li&gt;Optimized build configurations&lt;/li&gt;
&lt;li&gt;CORS properly configured&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. Code Organization
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Shared types in both applications&lt;/li&gt;
&lt;li&gt;Consistent naming conventions&lt;/li&gt;
&lt;li&gt;Clear file structure&lt;/li&gt;
&lt;li&gt;Separation of concerns&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates a production-ready micro frontends architecture using React, Vite, and Module Federation. &lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Micro Frontends
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Good Fit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large applications with multiple teams&lt;/li&gt;
&lt;li&gt;Need for independent deployments&lt;/li&gt;
&lt;li&gt;Different parts require different technologies&lt;/li&gt;
&lt;li&gt;Gradual migration from legacy systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not Ideal For:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small applications with a single team&lt;/li&gt;
&lt;li&gt;Tightly coupled features&lt;/li&gt;
&lt;li&gt;Limited DevOps resources&lt;/li&gt;
&lt;li&gt;Simple applications without scaling needs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add more micro frontends (e.g., user profile, checkout)&lt;/li&gt;
&lt;li&gt;Implement state management (Redux, Zustand)&lt;/li&gt;
&lt;li&gt;Add routing (React Router)&lt;/li&gt;
&lt;li&gt;Set up CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Add monitoring and logging&lt;/li&gt;
&lt;li&gt;Implement authentication/authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://module-federation.github.io/" rel="noopener noreferrer"&gt;Module Federation Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/originjs/vite-plugin-federation" rel="noopener noreferrer"&gt;Vite Plugin Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react-typescript-cheatsheet.netlify.app/" rel="noopener noreferrer"&gt;React TypeScript Cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/docs" rel="noopener noreferrer"&gt;Tailwind CSS Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Built with ❤️ for learning Micro Frontends Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This architecture provides a solid foundation for building scalable, maintainable frontend applications. By understanding these concepts and patterns, you can apply them to your own projects and teams.&lt;/p&gt;

</description>
      <category>react</category>
      <category>architecture</category>
      <category>microfrontend</category>
      <category>modulefederation</category>
    </item>
    <item>
      <title>Deploying a Vite + React app on Azure with Docker? I put together a complete step-by-step guide covering Dockerfiles, ACR, App Service, OIDC setup, and a GitHub Actions CI/CD pipeline. If you want to learn modern deployments, this will help a lot!</title>
      <dc:creator>Dimuthu Abeysinghe</dc:creator>
      <pubDate>Sun, 07 Dec 2025 00:43:51 +0000</pubDate>
      <link>https://forem.com/dimuthu7/deploying-a-vite-react-app-on-azure-with-docker-i-put-together-a-complete-step-by-step-guide-2ofd</link>
      <guid>https://forem.com/dimuthu7/deploying-a-vite-react-app-on-azure-with-docker-i-put-together-a-complete-step-by-step-guide-2ofd</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90" class="crayons-story__hidden-navigation-link"&gt;Deploying a React Vite App to Azure App Service Using Docker &amp;amp; GitHub Actions (with OIDC) 🚀&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/dimuthu7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F954465%2F5136723e-e1c4-409f-b3c6-a7fceb6a8a63.jpeg" alt="dimuthu7 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/dimuthu7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Dimuthu Abeysinghe
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Dimuthu Abeysinghe
                
              
              &lt;div id="story-author-preview-content-3089282" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/dimuthu7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F954465%2F5136723e-e1c4-409f-b3c6-a7fceb6a8a63.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Dimuthu Abeysinghe&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 6 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90" id="article-link-3089282"&gt;
          Deploying a React Vite App to Azure App Service Using Docker &amp;amp; GitHub Actions (with OIDC) 🚀
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/azure"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;azure&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubactions"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubactions&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>azure</category>
      <category>docker</category>
      <category>githubactions</category>
      <category>react</category>
    </item>
    <item>
      <title>Deploying a React Vite App to Azure App Service Using Docker &amp; GitHub Actions (with OIDC) 🚀</title>
      <dc:creator>Dimuthu Abeysinghe</dc:creator>
      <pubDate>Sat, 06 Dec 2025 17:04:53 +0000</pubDate>
      <link>https://forem.com/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90</link>
      <guid>https://forem.com/dimuthu7/deploying-a-react-vite-app-to-azure-app-service-using-docker-github-actions-with-oidc-2d90</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🔗 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/Dimuthu7/React-Azure-Deployment-Demo" rel="noopener noreferrer"&gt;https://github.com/Dimuthu7/React-Azure-Deployment-Demo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Modern web applications require fast builds, lightweight containers, and secure CI/CD automation. In this guide, we will deploy a &lt;strong&gt;React Vite application&lt;/strong&gt; into &lt;strong&gt;&lt;a href="https://azure.microsoft.com/en-us/products/app-service" rel="noopener noreferrer"&gt;Azure App Service&lt;/a&gt;&lt;/strong&gt; (Linux) using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; (Nginx for production)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/products/container-registry" rel="noopener noreferrer"&gt;Azure Container Registry (ACR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; CI/CD&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc" rel="noopener noreferrer"&gt;Azure OIDC (OpenID Connect)&lt;/a&gt; — passwordless authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the best practice method recommended by Microsoft because it uses short-lived identity tokens instead of long-lived secrets.&lt;/p&gt;

&lt;p&gt;Let’s walk through everything from &lt;strong&gt;creating the Vite project → writing Dockerfiles → configuring Azure → writing the GitHub Action workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 🛠 Create the React Vite App &amp;amp; Docker Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Create &lt;a href="https://vite.dev/guide/" rel="noopener noreferrer"&gt;Vite App&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest
cd your-project
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 — Create Dockerfiles
&lt;/h3&gt;

&lt;p&gt;We use &lt;strong&gt;two Dockerfiles&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;1️⃣ Dockerfile.dev — For running tests (optional)&lt;/p&gt;

&lt;p&gt;When running tests in CI, the production Dockerfile won’t work because it uses &lt;strong&gt;&lt;a href="https://nginx.org" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt;&lt;/strong&gt; (good for static hosting but cannot run tests).&lt;br&gt;
So we keep a separate dev Dockerfile.&lt;/p&gt;

&lt;p&gt;2️⃣ Dockerfile (Production) — For building and running the app on Azure&lt;/p&gt;

&lt;p&gt;Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ---------- Build Stage ----------
FROM node:lts-alpine AS builder

WORKDIR /app

# Copy only dependency files (faster builds via caching)
COPY package*.json ./
RUN npm install

# Copy the rest of the source code
COPY . .

# Build Vite production bundle
RUN npm run build


# ---------- Server Stage ----------
# Use Nginx to host static files
FROM nginx:stable-alpine

# Copy built files
COPY --from=builder /app/dist /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Start Nginx
CMD ["nginx", "-g", "daemon off;"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✔ This builds and serves the Vite app using Nginx&lt;br&gt;
✔ Perfect for Azure App Service (Linux) with Docker&lt;/p&gt;
&lt;h2&gt;
  
  
  2. ☁ Azure Setup (ACR + App Service + OIDC)
&lt;/h2&gt;

&lt;p&gt;We assume a clean Azure subscription.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1 — Create Resource Group
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az login
az group create --name rg-test --location eastus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rg-test&lt;/code&gt; → Your resource group&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eastus&lt;/code&gt; → Region&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step 2 — Create Azure Container Registry (ACR)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az acr create \
  --resource-group rg-test \
  --name acrReactApp \
  --sku Basic \
  --admin-enabled true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcq7dwhnvtevihhzw3ax0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcq7dwhnvtevihhzw3ax0.png" alt=" " width="500" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📌 Keep the following for GitHub Secrets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login Server → &lt;code&gt;acrreactapp.azurecr.io&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Username&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ACR stores your Docker images.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3 — Create App Service Plan
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az appservice plan create \
  --name vite-plan \
  --resource-group rg-test \
  --sku B1 \
  --is-linux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;B1&lt;/code&gt; → cheapest tier&lt;/li&gt;
&lt;li&gt;MUST be Linux for Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step 4 — Create the Web App (Docker)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az webapp create \
  --resource-group rg-test \
  --plan vite-plan \
  --name react-docker-app \
  --deployment-container-image-name acrreactapp.azurecr.io/viteapp:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The image doesn't need to exist yet — GitHub Actions will build and push it later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5 — Create Azure App Registration (for OIDC)
&lt;/h3&gt;

&lt;p&gt;Azure Portal → Azure Active Directory → &lt;strong&gt;App registrations&lt;/strong&gt; → New registration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;github-actions-deploy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Supported account types: &lt;strong&gt;Single tenant&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Redirect URI: leave empty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application (client) ID&lt;/li&gt;
&lt;li&gt;Directory (tenant) ID&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step 6 — Add Federated Credential (OIDC)
&lt;/h3&gt;

&lt;p&gt;Azure Portal → App Registration →&lt;br&gt;
&lt;strong&gt;Certificates &amp;amp; Secrets → Federated Credentials → Add credential&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fill the fields as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repository&lt;/td&gt;
&lt;td&gt;your-username/your-repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch&lt;/td&gt;
&lt;td&gt;main&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audience&lt;/td&gt;
&lt;td&gt;&lt;code&gt;api://AzureADTokenExchange&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;github-actions-main&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;✔ This enables passwordless login from GitHub to Azure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 7 — Assign Azure Role
&lt;/h3&gt;

&lt;p&gt;Azure Portal → Subscription → Access Control (IAM) → Add role assignment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role: &lt;strong&gt;Contributor&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Assign to: &lt;strong&gt;Service principal&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose the App Registration created above&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows GitHub workflow to deploy resources.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8 — Add GitHub Secrets
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Secret&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ACR_LOGIN_SERVER&lt;/td&gt;
&lt;td&gt;acrreactapp.azurecr.io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ACR_USERNAME&lt;/td&gt;
&lt;td&gt;from ACR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ACR_PASSWORD&lt;/td&gt;
&lt;td&gt;from ACR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AZURE_CLIENT_ID&lt;/td&gt;
&lt;td&gt;App Registration client ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AZURE_TENANT_ID&lt;/td&gt;
&lt;td&gt;Azure tenant ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AZURE_SUBSCRIPTION_ID&lt;/td&gt;
&lt;td&gt;Subscription ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  3. 🤖 GitHub Actions CI/CD Workflow
&lt;/h2&gt;

&lt;p&gt;Create file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;1️⃣ Trigger Workflow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  push:
    branches: ["main"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2️⃣ Permissions (IMPORTANT for OIDC)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permissions:
  id-token: write
  contents: read
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✔ Enables GitHub to request OIDC token&lt;br&gt;
✔ Required for passwordless Azure login&lt;/p&gt;

&lt;p&gt;3️⃣ Checkout Code&lt;br&gt;
&lt;code&gt;- uses: actions/checkout@v4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4️⃣ Install Dependencies &amp;amp; Build Vite App&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Install dependencies
  run: npm ci

- name: Build
  run: npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5️⃣ Login to Azure Using OIDC&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- uses: azure/login@v2
  with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens behind the scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GitHub asks for OIDC token&lt;/li&gt;
&lt;li&gt;GitHub issues short-lived token&lt;/li&gt;
&lt;li&gt;Azure verifies repository + branch&lt;/li&gt;
&lt;li&gt;Azure gives an Access Token&lt;/li&gt;
&lt;li&gt;Workflow becomes authenticated&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No passwords required.&lt;/p&gt;

&lt;p&gt;6️⃣ Login to ACR&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Login to ACR
  run: az acr login --name acrReactApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7️⃣ Build Docker Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Build Docker Image
  run: docker build -t acrreactapp.azurecr.io/viteapp:${{ github.sha }} .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;github.sha&lt;/code&gt;ensures each build uses a unique tag.&lt;/p&gt;

&lt;p&gt;8️⃣ Push Docker Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Push Image
  run: docker push acrreactapp.azurecr.io/viteapp:${{ github.sha }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;9️⃣ Deploy to Azure App Service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- uses: azure/webapps-deploy@v3
  with:
    app-name: react-docker-app
    images: acrreactapp.azurecr.io/viteapp:${{ github.sha }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. 🎉 Final Flow (End-to-End Overview)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GitHub → Build → Docker → ACR → Azure App Service → Live Website&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Deployment Flow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Developer pushes code → main&lt;/li&gt;
&lt;li&gt;GitHub Actions starts&lt;/li&gt;
&lt;li&gt;Install &amp;amp; build Vite&lt;/li&gt;
&lt;li&gt;Build Docker image&lt;/li&gt;
&lt;li&gt;Login to Azure via OIDC (no passwords)&lt;/li&gt;
&lt;li&gt;Push Docker image to ACR&lt;/li&gt;
&lt;li&gt;App Service pulls the image&lt;/li&gt;
&lt;li&gt;App restarts with new version&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4t2h5ussznju4gq7wvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4t2h5ussznju4gq7wvh.png" alt=" " width="233" height="823"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. 🔐 Why OIDC is Better Than Passwords?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Password/Secret-Based&lt;/th&gt;
&lt;th&gt;OIDC Token-Based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stored in GitHub secrets&lt;/td&gt;
&lt;td&gt;No secrets stored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk of leaks&lt;/td&gt;
&lt;td&gt;Zero secret exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Must rotate manually&lt;/td&gt;
&lt;td&gt;No rotation required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-lived&lt;/td&gt;
&lt;td&gt;Short-lived (~1 min)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be reused&lt;/td&gt;
&lt;td&gt;Cannot be reused&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;💯 OIDC is more secure, modern, and recommended by Microsoft.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Conclusion
&lt;/h2&gt;

&lt;p&gt;You now have a fully automated CI/CD pipeline using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React + Vite&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Azure Container Registry&lt;/li&gt;
&lt;li&gt;Azure App Service&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;OIDC (passwordless authentication)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup gives you:&lt;/p&gt;

&lt;p&gt;✔ Fast builds&lt;br&gt;
✔ Secure deployments&lt;br&gt;
✔ Scalable hosting&lt;br&gt;
✔ Zero manual steps&lt;/p&gt;

</description>
      <category>azure</category>
      <category>docker</category>
      <category>githubactions</category>
      <category>react</category>
    </item>
  </channel>
</rss>
