見出し画像

第八回:マイクロフロントエンドのデプロイメント

「各アプリのデプロイのタイミングをどう合わせればいい?」
「一部の機能だけ先にリリースしたい...」
「デプロイに失敗したときの影響を小さくしたい...」

マイクロフロントエンドの大きな魅力の一つが、独立したデプロイです。今回は、安全で効率的なデプロイ方法を見ていきましょう。

従来のデプロイとの違い

従来のモノリスなアプリケーション

1つのアプリ
└── 1回のデプロイで全ての機能をリリース

マイクロフロントエンドの場合

複数のアプリ
├── 商品一覧アプリ(個別にデプロイ可能)
├── カートアプリ(個別にデプロイ可能)
└── 注文アプリ(個別にデプロイ可能)

デプロイの基本戦略

1. 独立デプロイ

各アプリを独立してデプロイできる構成を作ります

# GitHub Actions例(商品一覧アプリ用)
name: Deploy Product App

on:
  push:
    paths:
      - 'apps/product/**'  # 商品一覧アプリの変更時のみ実行

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Build
        working-directory: ./apps/product
        run: npm run build
        
      - name: Deploy
        run: |
          # AWS S3にデプロイする例
          aws s3 sync dist/ s3://my-bucket/product-app/

2. バージョン管理

各アプリのバージョンを管理する仕組みを作ります

// manifest.json
{
  "apps": {
    "product": {
      "version": "1.2.0",
      "url": "https://cdn.example.com/product/1.2.0/",
      "integrity": "sha384-..."
    },
    "cart": {
      "version": "1.1.0",
      "url": "https://cdn.example.com/cart/1.1.0/",
      "integrity": "sha384-..."
    }
  }
}

// コンテナアプリでの読み込み
async function loadApp(name) {
  const manifest = await fetch('/manifest.json').then(r => r.json());
  const app = manifest.apps[name];
  
  const script = document.createElement('script');
  script.src = app.url;
  script.integrity = app.integrity;
  document.head.appendChild(script);
}

3. 段階的なロールアウト

新機能を徐々にリリースする仕組みを実装

// フィーチャーフラグの実装
const features = {
  // ユーザーの10%に新UIを表示
  newProductUI: {
    enabled: true,
    rolloutPercentage: 10
  },
  
  // 特定の条件のユーザーに新機能を表示
  newCheckout: {
    enabled: true,
    condition: (user) => user.isPremium
  }
};

// 使用例
function ProductList() {
  if (isFeatureEnabled('newProductUI')) {
    return <NewProductUI />;
  }
  return <OldProductUI />;
}

デプロイの自動化

1. CI/CDパイプラインの構築

# 共通の設定(.github/workflows/deploy.yml)
name: Deploy

on:
  push:
    branches: [main]

jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      apps: ${{ steps.set-matrix.outputs.apps }}
    steps:
      - uses: actions/checkout@v2
      
      - id: set-matrix
        run: |
          # 変更があったアプリを検出
          CHANGED_APPS=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep '^apps/' | cut -d/ -f2 | uniq)
          echo "::set-output name=apps::$CHANGED_APPS"

  deploy:
    needs: detect-changes
    strategy:
      matrix:
        app: ${{ fromJson(needs.detect-changes.outputs.apps) }}
    steps:
      - name: Deploy ${{ matrix.app }}
        run: |
          # アプリごとのデプロイ処理

2. ロールバック戦略

// バージョン履歴の管理
const versionHistory = {
  "product": [
    { version: "1.2.0", date: "2024-01-03", stable: true },
    { version: "1.1.0", date: "2024-01-01", stable: true }
  ]
};

// ロールバック用の関数
async function rollback(appName) {
  const versions = versionHistory[appName];
  const lastStableVersion = versions.find(v => v.stable);
  
  if (lastStableVersion) {
    await deployVersion(appName, lastStableVersion.version);
    notifyTeam(`${appName} rolled back to ${lastStableVersion.version}`);
  }
}

トラブルシューティング

1. デプロイ失敗時の対応

// ヘルスチェックの実装
async function checkAppHealth(appName, version) {
  try {
    // アプリの主要機能をチェック
    const response = await fetch(`/${appName}/health`);
    const metrics = await response.json();
    
    // 問題があれば自動ロールバック
    if (metrics.errorRate > 0.1) {  // エラー率10%超
      await rollback(appName);
      return false;
    }
    
    return true;
  } catch (error) {
    console.error(`Health check failed: ${appName}`, error);
    return false;
  }
}

2. パフォーマンスモニタリング

// パフォーマンス監視の実装
function monitorPerformance(appName) {
  // ロード時間の計測
  const loadTime = performance.now();
  
  // Core Web Vitalsの計測
  new PerformanceObserver((list) => {
    const metrics = list.getEntries();
    metrics.forEach(metric => {
      sendToAnalytics({
        app: appName,
        metricName: metric.name,
        value: metric.value
      });
    });
  }).observe({ entryTypes: ['web-vitals'] });
}

まとめ

マイクロフロントエンドのデプロイでは

  • 独立したデプロイを可能に

  • バージョン管理を適切に

  • 段階的なロールアウトを検討

  • 自動化とモニタリングを実装

が重要です。

次回は、マイクロフロントエンドの監視と運用について、より詳しく見ていきます。

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