Chuyển đến nội dung chính

Bài 12: Webpack Module Federation & Vite — Deep Dive

Hands-on với Module Federation từ zero. Cấu hình Host/Remote apps. Shared dependencies management. Vite Federation plugin. Error boundaries và fallback strategies.

🏗️ Kiến trúc — Bài 12 Bài 12: Webpack Module Federation & Vite — Deep Dive

Thiết kế hệ thống Microservices & Micro Frontend — Từ cơ bản đến Production

Phần 4: Micro Frontend — Kiến trúc & Nguyên lý

xdev.asia

Giới thiệu

Module Federation là tính năng game-changing của Webpack 5, cho phép nhiều builds chia sẻ code tại runtime. Bài này hands-on cấu hình từ zero.

Module Federation — Host & Remote runtime loading


1. Khái niệm cốt lõi

ConceptMô tả
HostApp load remote modules (Shell App)
RemoteApp expose modules cho host (MFE)
SharedDependencies chia sẻ giữa host & remote
remoteEntry.jsManifest file chứa thông tin về remote modules
┌─────────────────────────────┐
│ Browser                     │
│  Shell App (Host)           │
│  ┌─────────────────────┐    │
│  │ import('product/    │────────► remoteEntry.js (CDN)
│  │   ProductList')     │    │     → chunk-abc.js
│  └─────────────────────┘    │
│  Shared: React 18.2.0       │
│  (loaded ONCE)              │
└─────────────────────────────┘

2. Cấu hình Host (Shell App)

// webpack.config.js (Shell App)
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      remotes: {
        product: 'product@https://product.cdn.com/remoteEntry.js',
        cart: 'cart@https://cart.cdn.com/remoteEntry.js',
      },
      shared: {
        react: { singleton: true, requiredVersion: '^18.2.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.2.0' },
      },
    }),
  ],
};

3. Cấu hình Remote (Product MFE)

// webpack.config.js (Product MFE)
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'product',
      filename: 'remoteEntry.js',
      exposes: {
        './ProductList': './src/components/ProductList',
        './ProductDetail': './src/components/ProductDetail',
      },
      shared: {
        react: { singleton: true, requiredVersion: '^18.2.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.2.0' },
      },
    }),
  ],
};

4. Sử dụng trong Host

import React, { Suspense } from 'react';

const ProductList = React.lazy(() => import('product/ProductList'));
const MiniCart = React.lazy(() => import('cart/MiniCart'));

function App() {
  return (
    <div>
      <Header />
      <MFEErrorBoundary>
        <Suspense fallback={<div>Loading products...</div>}>
          <ProductList />
        </Suspense>
      </MFEErrorBoundary>
      <Footer />
    </div>
  );
}

5. Error Boundary cho Remote MFE

class MFEErrorBoundary extends React.Component {
  state = { hasError: false };
  
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  
  render() {
    if (this.state.hasError) {
      return <div>MFE unavailable. <button onClick={() => 
        this.setState({ hasError: false })}>Retry</button></div>;
    }
    return this.props.children;
  }
}

6. Shared Dependencies Management

shared: {
  react: {
    singleton: true,         // Chỉ load 1 version
    requiredVersion: '^18.2.0',
    eager: false,            // Lazy load (recommended)
    strictVersion: false,    // Cho phép minor version khác
  },
}

Version conflict resolution:

Host: [email protected]
Remote A: [email protected]  → Dùng shared (Host's version)
Remote B: [email protected]  → singleton → dùng 18.2.0 (warning)
Remote C: [email protected]  → strictVersion=true → ERROR

7. Vite Module Federation

// vite.config.js (Remote)
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    react(),
    federation({
      name: 'product',
      filename: 'remoteEntry.js',
      exposes: {
        './ProductList': './src/components/ProductList',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
});

Tóm tắt

  • Module Federation = runtime code sharing giữa independent builds
  • Host load Remote modules qua remoteEntry.js
  • Shared dependencies: singleton mode tránh duplicate React
  • Error Boundary bắt buộc cho production
  • Vite hỗ trợ qua plugin, syntax tương tự

Bài tiếp theo: Bài 13: Shell Application — Routing, Layout & Orchestration