マイクロフロントエンドのカスタムフレームワーク実装ガイド

マイクロフロントエンドのカスタムフレームワーク

1. サブアプリケーションの統合

Vue2アプリケーション

const webpack = require('webpack');
const path = require('path');

module.exports = {
  devServer: {
    port: 9004,
    headers: {
      'Access-Control-Allow-Origin': '*'
    }
  },
  configureWebpack: {
    output: {
      library: 'vue2App',
      libraryTarget: 'umd'
    }
  }
};
import Vue from 'vue';
import App from './App.vue';

let vueInstance = null;

export const bootstrap = () => {
  vueInstance = new Vue({
    render: h => h(App)
  }).$mount('#app-container');
};

export const mount = () => {
  if (!vueInstance) bootstrap();
};

export const unmount = () => {
  vueInstance.$destroy();
  vueInstance = null;
};

Vue3アプリケーション

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
  devServer: {
    port: 9005,
    headers: { 'Access-Control-Allow-Origin': '*' }
  },
  configureWebpack: {
    output: {
      library: 'vue3App',
      libraryTarget: 'umd'
    }
  }
});
import { createApp } from 'vue';
import App from './App.vue';

let appInstance = null;

export const mount = () => {
  appInstance = createApp(App);
  appInstance.mount('#app-container');
};

export const unmount = () => {
  appInstance.unmount();
  appInstance = null;
};

Reactアプリケーション

module.exports = {
  output: {
    library: 'reactApp',
    libraryTarget: 'umd',
    publicPath: 'http://localhost:9002/'
  },
  devServer: {
    port: 9002,
    headers: { 'Access-Control-Allow-Origin': '*' }
  }
};
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

export const mount = () => {
  ReactDOM.render(<App />, document.getElementById('app-container'));
};

export const unmount = () => {
  const container = document.getElementById('app-container');
  if (container) ReactDOM.unmountComponentAtNode(container);
};

2. メインアプリケーションでのサブアプリ登録

const microApps = [
  {
    name: 'vue2-app',
    entry: '//localhost:9004',
    container: '#app-container',
    activeRule: '/vue2'
  },
  {
    name: 'vue3-app',
    entry: '//localhost:9005',
    container: '#app-container',
    activeRule: '/vue3'
  }
];

3. ルートインターセプトの実装

const originalPushState = window.history.pushState;
window.history.pushState = function(...args) {
  const result = originalPushState.apply(this, args);
  window.dispatchEvent(new CustomEvent('microfrontend-route-change'));
  return result;
};

4. ライフサイクル管理

const lifecycles = {
  beforeMount: [],
  afterMount: [],
  beforeUnmount: []
};

export const registerLifecycle = (type, callback) => {
  lifecycles[type].push(callback);
};

export const executeLifecycles = async (type) => {
  for (const callback of lifecycles[type]) {
    await callback();
  }
};

5. HTMLの読み込みと解析

export const loadApplicationHTML = async (url) => {
  const response = await fetch(url);
  const html = await response.text();
  const parser = new DOMParser();
  return parser.parseFromString(html, 'text/html');
};

6. 実行環境の分離

class Sandbox {
  constructor() {
    this.proxyWindow = {};
  }
  
  execute(code) {
    const executeCode = `(function(window) {
      ${code}
    })(this.proxyWindow)`;
    eval(executeCode);
  }
}

7. CSSスタイルの分離

const scopedCSS = (css, scopeId) => {
  return css.replace(/([^{]+){/g, (match, selector) => {
    return `${selector}[data-scope="${scopeId}"] {`;
  });
};

8. アプリケーション間通信

class EventBus {
  constructor() {
    this.events = {};
  }
  
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  }
  
  on(event, callback) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(callback);
  }
}

window.microFrontendEventBus = new EventBus();

9. グローバル状態管理

class GlobalStore {
  constructor(initialState = {}) {
    this.state = initialState;
    this.subscribers = [];
  }
  
  setState(newState) {
    this.state = { ...this.state, ...newState };
    this.subscribers.forEach(subscriber => subscriber(this.state));
  }
  
  subscribe(callback) {
    this.subscribers.push(callback);
  }
}

window.globalStore = new GlobalStore();

10. パフォーマンス最適化

export const prefetchApplications = async (apps) => {
  const prefetchPromises = apps.map(app => {
    return fetch(app.entry).then(response => response.text());
  });
  
  await Promise.all(prefetchPromises);
};

既存マイクロフロントエンドフレームワーク

Qiankunフレームワーク

QiankunはSingle-SPAをベースにしたマイクロフロントエンドフレームワークで、サンドボックス、プリフェッチ、アプリケーション間通信などの機能を提供します。

Single-SPAフレームワーク

Single-SPAはマイクロフロントエンドのルーティングとライフサイクル管理を担当するコアライブラリで、様々なフレームワークの統合を可能にします。

タグ: マイクロフロントエンド Vue React javascript webpack

7月28日 06:48 投稿