見出し画像

第四回:Module Federationで始めるマイクロフロントエンド

「WebpackのModule Federationって何?」
「なんでみんなModule Federationを使うようになってきたの?」

最近、マイクロフロントエンドの実装方法として、Module Federationが注目を集めています。今回は、実際のコードを見ながら、その魅力を探っていきましょう。

Module Federationって何?

簡単に言うと、「複数のアプリケーションでコードを共有する仕組み」です。

従来のマイクロフロントエンドでは

// 従来の方法(iframeやJavaScriptでの読み込み)
<iframe src="http://app1.example.com"></iframe>
<iframe src="http://app2.example.com"></iframe>

Module Federationでは

// Module Federationを使った方法
import { Button } from 'app1/components';
import { Form } from 'app2/components';

// 別のアプリのコンポーネントを直接使える!
<Button onClick={handleClick}>送信</Button>
<Form onSubmit={handleSubmit} />

大きな違いは、別のアプリのコードをあたかも自分のアプリのコードのように使えるということです。

なぜModule Federationが人気なの?

1. 開発体験が自然

普段のReactやVueの開発と同じような感覚で書けます

// 通常のReactコンポーネント
import { Button } from './components/Button';

// Module Federationを使ったコンポーネント
import { Button } from 'shared/Button';

// 使い方は同じ!
function App() {
  return <Button>クリック</Button>;
}

2. パフォーマンスが良い

必要なコードだけを読み込めます

// 必要になった時点で読み込み
const Button = React.lazy(() => import('shared/Button'));

function App() {
  return (
    <Suspense fallback="読み込み中...">
      <Button>クリック</Button>
    </Suspense>
  );
}

3. 開発効率が上がる

共通のコンポーネントを簡単に共有できます

// 共通UIライブラリとして公開
// shared-ui/webpack.config.js
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shared_ui',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button',
        './Input': './src/Input',
        './Card': './src/Card',
      }
    })
  ]
};

実際に試してみよう

簡単な例を作ってみましょう。商品一覧とカートの機能を別々のアプリケーションとして実装します。

1. ホストアプリ(メインの画面)の設定

// webpack.config.js
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        productApp: 'product@http://localhost:3001/remoteEntry.js',
        cartApp: 'cart@http://localhost:3002/remoteEntry.js'
      }
    })
  ]
};

// App.js
const ProductList = React.lazy(() => import('productApp/ProductList'));
const Cart = React.lazy(() => import('cartApp/Cart'));

function App() {
  return (
    <div>
      <h1>私のECサイト</h1>
      <Suspense fallback="読み込み中...">
        <ProductList />
        <Cart />
      </Suspense>
    </div>
  );
}

2. 商品一覧アプリの設定

// webpack.config.js
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'product',
      filename: 'remoteEntry.js',
      exposes: {
        './ProductList': './src/ProductList'
      }
    })
  ]
};

// ProductList.js
function ProductList() {
  return (
    <div>
      <h2>商品一覧</h2>
      {/* 商品一覧の実装 */}
    </div>
  );
}

よくあるつまずきポイント

1. バージョンの不一致

// 解決策:shared設定で明示的にバージョンを指定
new ModuleFederationPlugin({
  shared: {
    react: {
      singleton: true,
      requiredVersion: '^17.0.0'
    }
  }
});

2. スタイルの衝突

// 解決策:CSS Modulesを使う
import styles from './Button.module.css';

function Button() {
  return <button className={styles.button}>クリック</button>;
}

まとめ

Module Federationは、マイクロフロントエンドの実装をより自然で効率的なものにしてくれます。
特に

  • 普段の開発スタイルを維持できる

  • パフォーマンスを確保できる

  • コードの共有が簡単

次回は、Module Federationを使った際のルーティング戦略について、より詳しく見ていきましょう。

いいなと思ったら応援しよう!