본문 바로가기

Vue 실습

[모듈 페더레이션]mhome과 remote2를 연결하여 모듈 페더레이션 by vue.cofig.js

728x90
 

mhome과 remote2를 연결하여 모듈 페더레이션(Module Federation)을 설정하는 과정을 처음부터 차근차근 설명합니다.


1. vue-cli 자동 구성

remote2를 vue-cli로 새로 구성합니다.

vue create remote2

2. remote2 설정

remote2는 Webpack 기반으로 동작하며 vue.config.js에서 Module Federation을 설정합니다.

vue.config.js

const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  publicPath: 'auto',
  configureWebpack: {
    plugins: [
      new ModuleFederationPlugin({
        name: 'remote2',
        filename: 'remoteEntry.js',
        exposes: {
          './ExposedComponent': './src/components/ExposedComponent.vue',
        },
        shared: {
          vue: {
            singleton: true,
            strictVersion: true,
            requiredVersion: '^3.4.0',
          },
        },
      }),
    ],
    experiments: {
      outputModule: false, // ESM 대신 var 형식으로 설정
    },
  },
  chainWebpack: (config) => {
    // splitChunks 비활성화
    config.optimization.delete('splitChunks');
    config.module.rule('ts').uses.delete('thread-loader');
    config.module.rule('tsx').uses.delete('thread-loader');
  },
  devServer: {
    port: 5003,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
};

ExposedComponent.vue

remote2에서 노출할 컴포넌트.

 
<template>
  <div>
    <h2>Exposed Component from Remote2</h2>
    <p>This is a shared component from Remote2.</p>
  </div>
</template>

<script setup>
</script>

<style scoped>
h2 {
  color: #42b983;
}
</style>

 


3. mhome 설정

mhome은 Vite 기반 Host 애플리케이션으로, Module Federation을 설정합니다.

vite.config.js

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'mhome',
      filename: 'remoteEntry.js',
      remotes: {
        remote2: {
          external: 'http://localhost:5003/remoteEntry.js',
          format: 'var', // Webpack과 호환성
        },
      },
      shared: {
        vue: {
          singleton: true,
          strictVersion: true,
          requiredVersion: '^3.4.0',
        },
      },
    }),
  ],
  server: {
    port: 5000,
    strictPort: true,
  },
  build: {
    target: 'esnext',
    rollupOptions: {
      output: {
        format: 'esm',
      },
    },
  },
});

App.vue

mhome에서 remote2의 컴포넌트를 동적으로 로드합니다.

 
<template>
  <h1>Welcome to mhome</h1>
  <p>This is the host app in the mono repository.</p>
  <h3>Remote2 Component:</h3>
  <component :is="RemoteExposed2" v-if="RemoteExposed2" />
  <p v-else>Loading remote2 component...</p>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';

const RemoteExposed2 = ref(null);

onMounted(async () => {
  try {
    RemoteExposed2.value = (await import('remote2/ExposedComponent')).default;
  } catch (err) {
    console.error('Error loading remote2 component:', err);
  }
});
</script>

4. 명령어

remote2

# remote2 디렉토리로 이동
cd remote2

# 패키지 설치 및 실행
yarn install
yarn serve

mhome

\
# mhome 디렉토리로 이동
cd mhome

# 패키지 설치 및 실행
pnpm install
pnpm dev​

5. 주요 이슈 및 해결

1. splitChunks 비활성화

  • 원인: Webpack에서 splitChunks 설정이 활성화되면 동적으로 로드되는 리모트 파일에 충돌이 발생.
  • 해결: chainWebpack에서 config.optimization.delete('splitChunks') 추가.

2. TypeError: Cannot read properties of undefined (reading 'init')

  • 원인: shared 설정 불일치.
  • 해결: shared.vue에 singleton: true, strictVersion: true 설정 추가.

3. remoteEntry.js: Unexpected token 'export'

  • 원인: Webpack에서 library.type: 'module' 사용.
  • 해결: library.type: 'var'로 변경.

6. 결과

  • mhome에서 remote2의 컴포넌트를 성공적으로 불러올 수 있음.
  • 모든 구성 및 설정이 완료되어 호스트와 리모트 간의 통신이 안정적으로 동작.
728x90