Ketika sebuah aplikasi web bertumbuh dari skala kecil menjadi platform skala enterprise dengan puluhan fitur kompleks, basis kode (codebase) di dalam repositori tunggal (monolithic frontend) cenderung menjadi sangat besar, rumit, dan lambat untuk dikembangkan. Tim pengembang yang terbagi menjadi beberapa departemen akan mulai saling bertabrakan saat melakukan pengiriman kode (push), proses pengujian (testing) memakan waktu berjam-jam, dan satu kesalahan kecil di satu fitur dapat merusak dan melumpuhkan seluruh fungsi website secara total.
Untuk mengatasi hambatan skalabilitas ini, industri rekayasa perangkat lunak mengadaptasi prinsip arsitektur mikroservis (microservices) backend ke sisi antarmuka pengguna, yang dikenal sebagai Arsitektur Micro-Frontends. Melalui fitur revolusioner Webpack Module Federation, tim developer dapat memecah aplikasi web raksasa menjadi potongan-potongan aplikasi independen yang dapat dikompilasi, dideploy, dan dijalankan secara dinamis saat runtime tanpa memerlukan integrasi iframe yang kaku atau pembungkusan paket npm yang merepotkan.
Memahami Konsep Webpack Module Federation
Sebelum Webpack 5 merilis Module Federation, penggabungan beberapa aplikasi frontend yang terpisah di satu halaman web sangat sulit dilakukan secara efisien. Developer sering kali terpaksa menggunakan tag <iframe> yang lambat dan mengisolasi memori secara kaku, atau mempublikasikan setiap komponen sebagai pustaka (library) npm privat yang mengharuskan kompilasi ulang seluruh situs utama setiap kali ada pembaruan visual minor.
Module Federation merombak total paradigma ini dengan memungkinkan sebuah aplikasi web secara dinamis memuat kode JavaScript dari aplikasi web lain yang di-hosting di server atau domain yang berbeda saat runtime.
Dalam ekosistem ini, kita mengenal tiga istilah peran aplikasi:
- Host (Container): Aplikasi web utama yang bertindak sebagai pembungkus luar dan bertanggung jawab untuk merender tata letak layout dasar serta memutuskan kapan komponen remote harus dimuat.
- Remote: Aplikasi web independen yang mengekspos (exports) komponen, modul, atau fungsi tertentu agar dapat digunakan oleh aplikasi Host.
- Shared: Daftar pustaka ketergantungan bersama (shared dependencies seperti React atau Lodash) yang dikonfigurasikan agar hanya diunduh satu kali saja oleh browser pengunjung guna menghemat ukuran file pemuatan halaman.
┌────────────────────────────────────────────────────────┐
│ APLIKASI HOST (Container) │
│ │
│ ┌───────────────────────┐ ┌──────────────────────┐ │
│ │ Remote A (Keranjang) │ │ Remote B (Rekomendasi)│ │
│ │ (Domain: cart.web.net)│ │ (Domain: rec.web.net)│ │
│ └───────────────────────┘ └──────────────────────┘ │
└────────────────────────────────────────────────────────┘
Rumus Optimasi Ukuran Bundel Transmisi ($S_{\text{shared}}$)
Salah satu keunggulan terbesar dari Module Federation adalah kemampuannya untuk mendeteksi dan menggunakan versi library yang sama dari memori cache browser. Jika Host dan Remote sama-sama menggunakan React, browser hanya akan mengunduh React satu kali.
Secara matematis, ukuran total file bundel JavaScript yang harus diunduh oleh browser pengunjung ($S_{\text{shared}}$) saat memuat halaman host yang berisi sebanyak $n$ buah komponen remote dapat dioptimalkan berdasarkan rumus berikut:
$$S_{\text{shared}} = \sum_{i=1}^{n} S_{\text{remote}_i} – (n – 1) \times S_{\text{shared\_deps}}$$
Di mana:
- $S_{\text{remote}_i}$ = Ukuran fisik file independen dari aplikasi remote ke-$i$ (KB).
- $S_{\text{shared\_deps}}$ = Ukuran kumulatif dari pustaka ketergantungan bersama (seperti
react,react-dom) yang dideklarasikan dalam konfigurasi shared (KB).
Dampak Teknis: Tanpa adanya sistem Module Federation, nilai pengurang $(n – 1) \times S_{\text{shared\_deps}}$ akan bernilai $0$ karena setiap remote dipaksa membungkus library React mereka sendiri ke dalam bundelnya, yang menyebabkan pembengkakan ukuran file loading awal dan memperlambat skor performa LCP (Largest Contentful Paint) website Anda secara signifikan.
Panduan Taktis: Konfigurasi Webpack Module Federation
Berikut adalah langkah-langkah praktis untuk mengonfigurasi hubungan Micro-Frontends antara aplikasi Remote (yang membuat komponen) dan aplikasi Host (yang memuat komponen) menggunakan React:
Langkah 1: Konfigurasi pada Aplikasi Remote (webpack.config.js)
Aplikasi Remote harus mendeklarasikan komponen apa saja yang ingin diekspos ke publik menggunakan modul plugin ModuleFederationPlugin:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container;
const path = require("path");
module.exports = {
entry: "./src/index",
mode: "development",
devServer: {
port: 3001, // Remote berjalan di port 3001
},
output: {
publicPath: "auto",
},
plugins: [
new ModuleFederationPlugin({
name: "app_remote",
filename: "remoteEntry.js", // File manifes petunjuk pemuatan dinamis
exposes: {
"./TombolBeli": "./src/components/TombolBeli", // Ekspos komponen TombolBeli
},
shared: {
react: { singleton: true, requiredVersion: "^18.0.0" },
"react-dom": { singleton: true, requiredVersion: "^18.0.0" },
},
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};
Langkah 2: Konfigurasi pada Aplikasi Host (webpack.config.js)
Aplikasi Host harus mendaftarkan alamat file manifes remoteEntry.js milik Remote agar dapat mengimpor komponen tersebut secara asinkron:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
entry: "./src/index",
mode: "development",
devServer: {
port: 3000, // Host berjalan di port 3000
},
plugins: [
new ModuleFederationPlugin({
name: "app_host",
remotes: {
// Daftarkan remote dengan alias 'app_remote'
app_remote: "app_remote@http://localhost:3001/remoteEntry.js",
},
shared: {
react: { singleton: true, requiredVersion: "^18.0.0" },
"react-dom": { singleton: true, requiredVersion: "^18.0.0" },
},
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};
Langkah 3: Mengimpor Komponen Remote di Aplikasi Host (React)
Di sisi kode aplikasi Host, Anda dapat memanggil komponen milik Remote secara dinamis menggunakan fitur React.lazy dan membungkusnya di dalam komponen React.Suspense untuk menangani status loading:
import React, { lazy, Suspense } from "react";
// Muat komponen TombolBeli dari remote secara asinkron saat runtime
const TombolBeliRemote = lazy(() => import("app_remote/TombolBeli"));
function AppHost() {
return (
<div style={{ padding: "20px", fontFamily: "sans-serif" }}>
<h1>Dashboard Aplikasi Utama (Host)</h1>
<p>Berikut adalah komponen produk yang dimuat dari server mikro terpisah:</p>
<Suspense fallback={<div>Memuat komponen eksternal...</div>}>
<TombolBeliRemote idProduk="105" />
</Suspense>
</div>
);
}
export default AppHost;
Perbandingan Arsitektur Pembangunan Frontend
Berikut adalah tabel matriks komparasi untuk membantu Anda memahami kelebihan dan kekurangan Module Federation dibandingkan metode integrasi frontend lainnya:
| Parameter Evaluasi | Monolith SPA (Single Codebase) | Tag Iframe Tradisional | Webpack Module Federation |
|---|---|---|---|
| Isolasi Kode | Nol (Seluruh kode tercampur di satu tempat). | Sangat Tinggi (Terisolasi penuh di browser). | Tinggi (Terpisah secara runtime namun tetap terintegrasi). |
| Kecepatan Runtime | Sangat Cepat setelah halaman selesai dimuat. | Lambat (Memakan konsumsi daya CPU & RAM berlebih). | Sangat Cepat (Sama seperti komponen lokal biasa). |
| Berbagi Library | Otomatis terbagi satu kali kompilasi. | Mustahil (Setiap iframe harus mengunduh ulang React). | Sangat Efisien (Mendukung fitur dependency sharing). |
| Kemandirian Rilis | Buruk (Satu tim menghambat rilis tim lainnya). | Sangat Baik (Setiap tim bisa deploy kapan saja). | Sangat Baik (Remote dideploy mandiri tanpa ganggu Host). |
| Kompleksitas Setup | Sangat Rendah (Sederhana untuk dikembangkan). | Rendah. | Sedang (Memerlukan konfigurasi Webpack yang presisi). |
FAQ: Tanya Jawab Seputar Micro-Frontends
Apa yang terjadi jika server aplikasi Remote (port 3001) mati saat pengguna membuka Host? Aplikasi Host akan mendeteksi kegagalan koneksi tersebut sebagai error pemuatan modul runtime. Untuk mencegah website utama Anda crash total (blank screen), pastikan Anda membungkus setiap komponen remote di dalam penangan error khusus React yang disebut Error Boundary. Jika Remote mati, Error Boundary akan merender tampilan alternatif (fallback UI) seperti teks “Gagal memuat widget” secara anggun tanpa mengganggu fungsi halaman web lainnya.
Apakah kita bisa menggabungkan framework yang berbeda (misal Host menggunakan React dan Remote menggunakan Vue)? Secara teknis Webpack Module Federation memungkinkan hal tersebut karena ia hanya mengirimkan kode JavaScript murni saat runtime. Namun, mencampurkan dua framework besar yang berbeda pada satu halaman web sangat tidak direkomendasikan karena akan memaksa browser mengunduh runtime engine React sekaligus Vue secara bersamaan, yang akan membuat ukuran loading halaman menjadi sangat berat dan merusak kenyamanan navigasi pengguna.
Apakah Module Federation ramah terhadap indeksasi robot SEO Google? Ya, sangat ramah jika Anda mengonfigurasikannya menggunakan arsitektur Server-Side Rendering (SSR) modern seperti framework Next.js yang mendukung Module Federation melalui pustaka khusus @module-federation/nextjs-mf. Dengan SSR, server akan menggabungkan komponen Host dan Remote menjadi HTML murni terlebih dahulu di sisi server sebelum dikirimkan ke robot perayap Googlebot.

Tinggalkan Balasan