All Resources
Tool
ViteMicro FrontendBuild
June 21, 2024

Vite Module Federation

Share code and dependencies across micro frontends with Vite's module federation.

Overview

Module Federation enables multiple independently deployed frontends to share code and dependencies. Build scalable micro frontend architectures.

Benefits

  • Independent Deployment: Deploy apps without coordinating
  • Shared Dependencies: Reduce bundle sizes by sharing packages
  • Dynamic Loading: Load applications at runtime
  • Team Autonomy: Different teams own different apps
  • Shared Component Libraries: Use common components

Setup

npm install -D @originjs/vite-plugin-federation

Host Application

// vite.config.ts - host app
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import federation from '@originjs/vite-plugin-federation'

export default defineConfig({
  plugins: [
    react(),
    federation({
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/components/Button.tsx',
        './useStore': './src/hooks/useStore.ts'
      },
      shared: ['react', 'react-dom']
    })
  ],
  build: {
    target: 'esnext',
    minify: false,
    cssCodeSplit: false
  }
})

Remote Application

// vite.config.ts - remote app
federation({
  name: 'products',
  filename: 'remoteEntry.js',
  exposes: {
    './ProductList': './src/pages/ProductList.tsx',
    './useProducts': './src/hooks/useProducts.ts'
  },
  remotes: {
    hostApp: 'http://localhost:3000/assets/remoteEntry.js'
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' }
  }
})

Use Remote Components

import React, { Suspense } from 'react'

const RemoteProductList = React.lazy(() => 
  import('products/ProductList')
)

export function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <RemoteProductList />
    </Suspense>
  )
}

Dynamic Loading

// Load remote app at runtime
async function loadRemoteApp(url: string) {
  const container = document.createElement('div')
  document.body.appendChild(container)

  const { mount } = await import(`${url}/remoteEntry.js`)
  mount(container)
}

await loadRemoteApp('http://localhost:3001')

Module Federation reduces frontend bundle sizes by 60-70% through dependency sharing.

Curated by

Shyam