
→ Vite로 host, remote1 패키지 생성, Rspack으로 remote2 패키지 생성
→ remote1 Button 컴포넌트 추가 후 Vite 빌드 후 http://localhost:3002/ 로컬 환경 띄움(remoteEntry.js 파일 생성)
(remoteEntry.js는 MF1에서 쓰는 remote 앱의 진입점 역할)

→ remote2 Button 컴포넌트 추가 후 Rsbuild 빌드 로컬 http://localhost:8080/ 로컬 환경 띄움(mf-manifest.json 파일 생성)
(mf-manifest.json은 MF2에서 쓰는 remote 모듈의 메타 정보(url, type 등...)을 담은 파일로 어느 빌드 환경에서도 호환이 가능)

→ host에 Vite config 설정으로 remote1 앱 "remoteApp"으로 선언 하여 remote1 패키지의 버튼을 가져와 사용

→ host main.jsx 진입점에 createInstance로 mf-manifest.json을 받아와 remote2 인스턴스 생성
→ 전역객체 globalThis에 remote2 인스턴스를 mf로 선언하고 앱 페이지 내에서 전역객체를 사용해 loadRemote로 remote2 패키지의 컴포넌트를 가져와 사용
(이 때 globalThis는 ES11이 지원되지 않는 옛날 브라우저에서는 사용이 불가하기에 Polyfill코드 작성이 필요)

MF1.0 방식의 빌드 시점 플러그인과 MF2.0 방식의 런타임 플러그인을 함께 사용하는 경우에도 충돌 없이 동작함을 확인함
(remote1은 Vite로 빌드된 컴포넌트, remote2는 Rspack으로 빌드된 컴포넌트로 구성됨)
프로덕션 환경에서는 remote1이 새로 배포되면 host도 함께 다시 빌드해야 정상 동작함. 빌드 시점에 remoteEntry.js 문자열 url을 가져와 번들에 포함되기 때문에,
만약 host를 새로 빌드하지 않으면 이전 버전의 remote1이 캐싱된 상태로 로드되면서 페이지 에러를 띄우거나 충돌이 발생할 수 있음
반면, remote2는 런타임에 remoteEntry.js를 동적으로 불러오기 때문에, remote2에 변경사항이 있어도 host에서는 새로고침만으로 최신 모듈을 로드할 수 있음.
remote1, remote2 모두 모듈명 변경 혹은 모듈 제거 시 런타임 에러가 발생할 수 있으므로, 이를 방지하기 위해 lazy import() 시 try/catch 기반의 예외 처리가 필요함.
아래는 MF1.0과 MF2.0의 런타임 동적 로딩 방식의 차이를 정리한 표이다.
특히, 독립적인 개별 배포가 필요한 대규모 프로젝트에서는 MF2 방식이 사실상 필수로 보이며,
MF2 방식에서는 초기 로딩 최적화 및 캐시 전략 수립이 함께 고려되어야 한다.

MF 2.0에서는 Manifest 프로토콜 도입으로 기존 MF1.0에서 처럼 remote 등록시 remoteEntry의 경로를 직접 명시하지 않는다.
빌드 시 mf-manifest.json이라는 JSON 메타파일을 생성하여, 런타임에서 mf-manifest.json파일을 fetch해 remoteApp을 동적으로 알아내어 remoteEntry.js를 로딩한다.
vite.config.js
/** MF 1.0 */
remotes: {
remoteApp: 'remoteApp@https://domain.com/remoteEntry.js'
}
mf-manifest.json
/** MF 2.0 */
{
"id": "remote_rspack",
"name": "remote_rspack",
"metaData": {
"name": "remote_rspack",
"type": "app",
"buildInfo": {
"buildVersion": "1.0.0",
"buildName": "remote-rspack"
},
"remoteEntry": {
"name": "remote_rspack.js", // 경로2
"path": "",
"type": "global"
},
"types": {
"path": "",
"name": "",
"zip": "@mf-types.zip",
"api": "@mf-types.d.ts"
},
"globalName": "remote_rspack",
"pluginVersion": "0.17.0",
"prefetchInterface": false,
"publicPath": "http://localhost:8080/" // 경로1
},
...shared,remotes,exposes
}
/** RemoteEntry.js 불러올때 publicPath+RemoteEntry.name 조합으로 불러옴 */
또한 MF 2.0에서는 preloadRemote가 추가되어 모듈 사용시 사전로딩이 가능하다. preload할 수 있는 요소로는 remoteEntry, expose한 모듈, 동기/비동기 유틸 함수, remote에 종속된 패키지 등이 있다.
미리 불러오기 때문에 모듈 remote 모듈 사용시 초기 로딩 지연을 최소화 시켜 즉시 렌더링 하여 UX를 향상시킬 수 있다. (예시: 로그인 직후 대시보드 진입, 탭이나 상세 페이지 hover 시 사전 호출 등..)
@module-federation/enhanced/webpack 사용하여 빌드 시 CopyTypesPlugin이 자동으로 remote의 타입파일들을 webpack 내부 훅을 이용해서 dist/@mf-types/remote 경로로 복사해준다.
webpack이 아닌 다른빌드 툴 사용시 수동 스크립트 처리로 dist/@mf-types/remote 복사해주어야 host에서 타입파일들을 읽어와 타입 힌팅을 제공받을 수 있다.
-> 다른 빌드 툴도 타입을 자동 생성해 줄 수 있으나 동적으로 받아오는경우에 따로 host에서 타입을 가져와야함.
