Membedah dynamic federation di Module Federation 2.0: memuat remote tanpa konfigurasi build-time via loadRemote, paket runtime-only, manifest-based loading untuk produksi, fallback dengan errorLoadRemote dan ErrorBoundary, serta progressive enhancement.

Sejauh ini kita mendeklarasikan remote secara statis di config host (remotes: { catalog: ... }). Itu bagus untuk memulai, tetapi kurang fleksibel: kalau tim ingin menambah remote baru tanpa me-rebuild host, atau ingin memilih remote mana yang aktif berdasarkan konfigurasi, kita butuh dynamic federation.
Mengapa penting? Karena salah satu janji utama microfrontend adalah independent deploy. Dengan dynamic federation, host tidak perlu di-build ulang setiap kali remote muncul/pergi — ia bisa memuat remote berdasarkan manifest saat runtime. Episode ini membahas cara melakukannya.
Module Federation 2.0 menyediakan API runtime loadRemote untuk memuat remote secara dinamis, tanpa mendeklarasikannya dulu di config host:
import { loadRemote } from '@module-federation/enhanced/runtime'
const CatalogApp = loadRemote<typeof import('catalog/CatalogApp')>('catalog/CatalogApp')loadRemote mengambil string name/export dan mengembalikan module yang bisa dipakai. Karena tidak ada config build-time, remote bisa di-resolve per env atau per konfigurasi.
@module-federation/runtimeAda dua cara memakai Module Federation:
| Mode | Paket | Kapan dipakai |
|---|---|---|
| Build plugin | @module-federation/vite / enhanced | Host dan remote yang di-build dengan plugin federasi |
| Runtime-only | @module-federation/runtime | Kebutuhan dynamic loading tanpa plugin build |
Dengan runtime-only, kalian bisa memuat remote secara murni dinamis — bahkan dari aplikasi yang tidak di-build dengan plugin federasi. Ini berguna untuk host yang menangani banyak remote dinamis atau integrasi di lingkungan terbatas.
Untuk produksi di CDN, kita memakai manifest sebagai pusat konfigurasi. mf-manifest.json berisi peta exports → chunk URL:
{
"id": "catalog",
"name": "catalog",
"exposes": {
"./CatalogApp": {
"id": "CatalogApp",
"import": "http://cdn.example.com/catalog/CatalogApp.js"
}
},
"shared": {
"react": { "singleton": true, "version": "19.0.0" }
}
}Host membaca manifest ini (bukan config build-time) untuk tahu apa yang bisa dimuat dan dari URL mana. Ini menjadi dasar deployment multi-remote di episode 14.
Karena remote dimuat secara runtime, ia bisa gagal — jaringan putus, CDN down, versi mismatch. Kita wajib menangani ini:
errorLoadRemote HookModule Federation menyediakan hook untuk menangkap kegagalan:
import { init } from '@module-federation/enhanced/runtime'
init({
errorLoadRemote: ({ id, error }) => {
if (id.startsWith('catalog')) {
return { default: CatalogFallback }
}
throw error
},
})Selain hook, bungkus remote dalam ErrorBoundary agar error tidak membawa halaman mati total — hanya bagian remote yang diganti fallback UI:
<ErrorBoundary fallback={<p>Bagian ini sementara tidak tersedia.</p>}>
<CatalogApp />
</ErrorBoundary>Important
Setiap remote wajib punya fallback. Ini bagian dari production checklist (episode 23). Host yang baik tidak pernah menampilkan layar putih penuh hanya karena satu remote gagal di-load.
Karena remote di-deploy ke CDN dan dimuat saat runtime, host bisa menerapkan progressive enhancement: mencoba memuat remote, dan jika gagal, men-degrade dengan pesan "bagian ini sementara tidak tersedia" sambil tetap menampilkan bagian lain yang sehat.
Untuk jaringan fluktuatif, tambahkan strategi retry — coba lagi setelah jeda singkat, atau pada navigasi berikutnya:
async function loadWithRetry(loader, retries = 2) {
let lastErr
for (let i = 0; i <= retries; i++) {
try {
return await loader()
} catch (e) {
lastErr = e
await new Promise((r) => setTimeout(r, 500))
}
}
throw lastErr
}Pada episode 9 ini, kalian telah memahami dynamic federation & runtime loading.
Inti yang harus dibawa pulang:
loadRemote memuat remote tanpa config build-time; runtime-only (@module-federation/runtime) untuk dynamic murni.mf-manifest.json) menyimpan peta exports → URL untuk produksi CDN.errorLoadRemote + React ErrorBoundary → remote gagal bukan halaman mati.Di episode 10 selanjutnya, kita akan membandingkan Module Federation 2.0: Webpack vs Rspack vs Vite — kapan memilih masing-masing bundler, konfigurasi migrasi antar bundler, dan build performance untuk monorepo besar. Pastikan dynamic loading kalian sudah berjalan!