Jelajahi JavaScript Module Federation, teknik revolusioner untuk membangun arsitektur micro-frontend yang skalabel dan mudah dipelihara. Pelajari manfaat, detail implementasi, dan praktik terbaiknya.
JavaScript Module Federation: Panduan Komprehensif Arsitektur Micro-Frontend
Dalam lanskap pengembangan web yang terus berkembang, membangun aplikasi besar yang kompleks dapat dengan cepat menjadi tugas yang menakutkan. Arsitektur monolitik tradisional sering kali mengarah pada basis kode yang terikat erat, menghambat skalabilitas, kemudahan pemeliharaan, dan deployment independen. Micro-frontend menawarkan alternatif yang menarik, memecah aplikasi menjadi unit-unit yang lebih kecil dan dapat di-deploy secara independen. Di antara berbagai teknik micro-frontend, JavaScript Module Federation menonjol sebagai solusi yang kuat dan elegan.
Apa itu JavaScript Module Federation?
JavaScript Module Federation, yang diperkenalkan oleh Webpack 5, memungkinkan aplikasi JavaScript untuk berbagi kode dan dependensi secara dinamis saat runtime. Berbeda dengan metode berbagi kode tradisional yang bergantung pada dependensi saat build-time, Module Federation memungkinkan aplikasi untuk memuat dan menjalankan kode dari aplikasi lain, bahkan jika mereka dibuat dengan teknologi atau versi library yang berbeda. Ini menciptakan arsitektur yang benar-benar terdistribusi dan terlepas (decoupled).
Bayangkan sebuah skenario di mana Anda memiliki beberapa tim yang mengerjakan bagian yang berbeda dari sebuah situs e-commerce besar. Satu tim mungkin bertanggung jawab atas katalog produk, tim lain untuk keranjang belanja, dan tim ketiga untuk otentikasi pengguna. Dengan Module Federation, setiap tim dapat mengembangkan, membangun, dan men-deploy micro-frontend mereka secara independen, tanpa harus khawatir tentang konflik atau dependensi dengan tim lain. Aplikasi utama ("host") kemudian dapat secara dinamis memuat dan me-render micro-frontend ini ("remote") saat runtime, menciptakan pengalaman pengguna yang mulus.
Konsep Utama Module Federation
- Host: Aplikasi utama yang mengonsumsi dan me-render modul remote.
- Remote: Aplikasi independen yang mengekspos modul untuk dikonsumsi oleh aplikasi lain.
- Modul Bersama (Shared Modules): Dependensi yang dibagikan antara host dan remote. Ini menghindari duplikasi dan memastikan versi yang konsisten di seluruh aplikasi.
- Plugin Module Federation: Plugin Webpack yang mengaktifkan fungsionalitas Module Federation.
Manfaat Module Federation
1. Deployment Independen
Setiap micro-frontend dapat di-deploy secara independen tanpa memengaruhi bagian lain dari aplikasi. Ini memungkinkan siklus rilis yang lebih cepat, mengurangi risiko, dan meningkatkan kelincahan. Sebuah tim di Berlin dapat men-deploy pembaruan pada katalog produk sementara tim keranjang belanja di Tokyo terus bekerja secara independen pada fitur mereka. Ini adalah keuntungan signifikan bagi tim yang terdistribusi secara global.
2. Peningkatan Skalabilitas
Aplikasi dapat diskalakan secara horizontal dengan men-deploy setiap micro-frontend di server terpisah. Ini memungkinkan pemanfaatan sumber daya yang lebih baik dan peningkatan kinerja. Misalnya, layanan otentikasi, yang sering menjadi hambatan kinerja, dapat diskalakan secara independen untuk menangani beban puncak.
3. Peningkatan Kemudahan Pemeliharaan
Micro-frontend lebih kecil dan lebih mudah dikelola daripada aplikasi monolitik, membuatnya lebih mudah untuk dipelihara dan di-debug. Setiap tim memiliki kepemilikan atas basis kode mereka sendiri, memungkinkan mereka untuk fokus pada area keahlian spesifik mereka. Bayangkan sebuah tim global yang berspesialisasi dalam gateway pembayaran; mereka dapat memelihara micro-frontend spesifik tersebut tanpa memengaruhi tim lain.
4. Agnostik Teknologi
Micro-frontend dapat dibangun menggunakan teknologi atau kerangka kerja yang berbeda, memungkinkan tim untuk memilih alat terbaik untuk pekerjaan itu. Satu micro-frontend mungkin dibangun dengan React, sementara yang lain menggunakan Vue.js. Fleksibilitas ini sangat berguna saat mengintegrasikan aplikasi lawas atau ketika tim yang berbeda memiliki preferensi atau keahlian yang berbeda.
5. Penggunaan Ulang Kode
Modul bersama dapat digunakan kembali di beberapa micro-frontend, mengurangi duplikasi kode dan meningkatkan konsistensi. Ini sangat berguna untuk komponen umum, fungsi utilitas, atau sistem desain. Bayangkan sistem desain yang konsisten secara global dibagikan di semua micro-frontend, memastikan pengalaman merek yang terpadu.
Mengimplementasikan Module Federation: Contoh Praktis
Mari kita bahas contoh sederhana tentang cara mengimplementasikan Module Federation menggunakan Webpack 5. Kita akan membuat dua aplikasi: aplikasi host dan aplikasi remote. Aplikasi remote akan mengekspos komponen sederhana yang akan dikonsumsi oleh aplikasi host.
Langkah 1: Menyiapkan Aplikasi Host
Buat direktori baru untuk aplikasi host dan inisialisasi proyek npm baru:
mkdir host-app
cd host-app
npm init -y
Instal Webpack dan dependensinya:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Buat file `webpack.config.js` di root aplikasi host dengan konfigurasi berikut:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'http://localhost:3000/', // Penting untuk Module Federation
},
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'] // Menambahkan preset react
}
}
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remote@http://localhost:3001/remoteEntry.js', // Menunjuk ke entri remote
},
shared: ['react', 'react-dom'], // Berbagi react
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Konfigurasi ini mendefinisikan titik masuk, direktori output, pengaturan server pengembangan, dan plugin Module Federation. Properti `remotes` menentukan lokasi file `remoteEntry.js` aplikasi remote. Properti `shared` mendefinisikan modul yang dibagikan antara aplikasi host dan remote. Kami membagikan 'react' dan 'react-dom' dalam contoh ini.
Buat file `index.html` di direktori `public`:
<!DOCTYPE html>
<html>
<head>
<title>Aplikasi Host</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Buat direktori `src` dan file `index.js` di dalamnya. File ini akan memuat komponen remote dan me-rendernya di aplikasi host:
import React from 'react';
import ReactDOM from 'react-dom/client';
import RemoteComponent from 'remoteApp/RemoteComponent';
const App = () => (
<div>
<h1>Aplikasi Host</h1>
<p>Ini adalah aplikasi host yang mengonsumsi komponen remote.</p>
<RemoteComponent />
</div>
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
Instal babel-loader dan preset-nya
npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react style-loader css-loader
Langkah 2: Menyiapkan Aplikasi Remote
Buat direktori baru untuk aplikasi remote dan inisialisasi proyek npm baru:
mkdir remote-app
cd remote-app
npm init -y
Instal Webpack dan dependensinya:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Buat file `webpack.config.js` di root aplikasi remote dengan konfigurasi berikut:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'http://localhost:3001/', // Penting untuk Module Federation
},
devServer: {
port: 3001,
hot: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'remote',
filename: 'remoteEntry.js',
exposes: {
'./RemoteComponent': './src/RemoteComponent.js', // Mengekspos komponen
},
shared: ['react', 'react-dom'], // Berbagi react
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Konfigurasi ini mirip dengan aplikasi host, tetapi dengan beberapa perbedaan utama. Properti `name` diatur ke `remote`, dan properti `exposes` mendefinisikan modul yang diekspos ke aplikasi lain. Dalam hal ini, kami mengekspos `RemoteComponent`.
Buat file `index.html` di direktori `public`:
<!DOCTYPE html>
<html>
<head>
<title>Aplikasi Remote</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Buat direktori `src` dan file `RemoteComponent.js` di dalamnya. File ini akan berisi komponen yang diekspos ke aplikasi host:
import React from 'react';
const RemoteComponent = () => (
<div style={{ border: '2px solid red', padding: '10px', margin: '10px' }}>
<h2>Komponen Remote</h2>
<p>Komponen ini dimuat dari aplikasi remote.</p>
</div>
);
export default RemoteComponent;
Buat direktori `src` dan file `index.js` di dalamnya. File ini akan me-render `RemoteComponent` saat aplikasi remote dijalankan secara independen (opsional):
import React from 'react';
import ReactDOM from 'react-dom/client';
import RemoteComponent from './RemoteComponent';
const App = () => (
<div>
<h1>Aplikasi Remote</h1>
<RemoteComponent />
</div>
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
Langkah 3: Menjalankan Aplikasi
Tambahkan skrip start ke kedua file `package.json`:
"scripts": {
"start": "webpack serve"
}
Mulai kedua aplikasi menggunakan `npm start`. Buka browser Anda dan navigasikan ke `http://localhost:3000`. Anda akan melihat aplikasi host me-render komponen remote. Komponen remote akan memiliki batas merah di sekelilingnya, yang menandakan bahwa itu dimuat dari aplikasi remote.
Konsep Lanjutan dan Pertimbangan
1. Pengelolaan Versi dan Kompatibilitas
Saat berbagi dependensi antar micro-frontend, penting untuk mempertimbangkan pengelolaan versi dan kompatibilitas. Module Federation menyediakan mekanisme untuk menentukan rentang versi dan menyelesaikan konflik. Alat seperti semantic versioning (semver) menjadi krusial dalam mengelola dependensi dan memastikan kompatibilitas di berbagai micro-frontend. Kegagalan dalam mengelola versi dengan benar dapat menyebabkan kesalahan runtime atau perilaku tak terduga, terutama dalam sistem kompleks dengan banyak micro-frontend.
2. Otentikasi dan Otorisasi
Mengimplementasikan otentikasi dan otorisasi dalam arsitektur micro-frontend memerlukan perencanaan yang cermat. Pendekatan umum termasuk menggunakan layanan otentikasi bersama atau mengimplementasikan otentikasi berbasis token. Keamanan adalah yang terpenting, dan sangat penting untuk mengikuti praktik terbaik untuk melindungi data sensitif. Misalnya, platform e-commerce mungkin memiliki micro-frontend otentikasi khusus yang bertanggung jawab untuk memverifikasi kredensial pengguna sebelum memberikan akses ke micro-frontend lain.
3. Komunikasi Antar Micro-Frontend
Micro-frontend sering kali perlu berkomunikasi satu sama lain untuk bertukar data atau memicu tindakan. Berbagai pola komunikasi dapat digunakan, seperti event, manajemen state bersama, atau panggilan API langsung. Memilih pola komunikasi yang tepat tergantung pada persyaratan spesifik aplikasi. Alat seperti Redux atau Vuex dapat digunakan untuk manajemen state bersama. Event kustom dapat digunakan untuk loose coupling dan komunikasi asinkron. Panggilan API dapat digunakan untuk interaksi yang lebih kompleks.
4. Optimalisasi Kinerja
Memuat modul remote dapat memengaruhi kinerja, terutama jika modulnya besar atau koneksi jaringan lambat. Mengoptimalkan ukuran modul, menggunakan code splitting, dan caching modul remote dapat meningkatkan kinerja. Lazy loading modul hanya saat dibutuhkan adalah teknik optimasi penting lainnya. Juga, pertimbangkan untuk menggunakan Content Delivery Network (CDN) untuk menyajikan modul remote dari lokasi yang secara geografis lebih dekat dengan pengguna akhir, sehingga mengurangi latensi.
5. Pengujian Micro-Frontend
Menguji micro-frontend memerlukan pendekatan yang berbeda dari menguji aplikasi monolitik. Setiap micro-frontend harus diuji secara independen, serta dalam integrasi dengan micro-frontend lainnya. Contract testing dapat digunakan untuk memastikan bahwa micro-frontend kompatibel satu sama lain. Unit test, integration test, dan end-to-end test semuanya penting untuk memastikan kualitas arsitektur micro-frontend.
6. Penanganan Kesalahan dan Pemantauan
Mengimplementasikan penanganan kesalahan dan pemantauan yang kuat sangat penting untuk mengidentifikasi dan menyelesaikan masalah dalam arsitektur micro-frontend. Sistem logging dan pemantauan terpusat dapat memberikan wawasan tentang kesehatan dan kinerja aplikasi. Alat seperti Sentry atau New Relic dapat digunakan untuk melacak kesalahan dan metrik kinerja di berbagai micro-frontend. Strategi penanganan kesalahan yang dirancang dengan baik dapat mencegah kegagalan berantai dan memastikan pengalaman pengguna yang tangguh.
Kasus Penggunaan untuk Module Federation
Module Federation sangat cocok untuk berbagai kasus penggunaan, termasuk:
- Platform E-commerce Besar: Memecah situs web menjadi unit-unit yang lebih kecil dan dapat di-deploy secara independen untuk katalog produk, keranjang belanja, otentikasi pengguna, dan checkout.
- Aplikasi Perusahaan: Membangun dasbor dan portal kompleks dengan tim yang berbeda yang bertanggung jawab untuk bagian yang berbeda.
- Sistem Manajemen Konten (CMS): Memungkinkan pengembang untuk membuat dan men-deploy modul atau plugin kustom secara independen.
- Arsitektur Microservices: Mengintegrasikan aplikasi front-end dengan backend microservices.
- Progressive Web Apps (PWA): Memuat dan memperbarui fitur secara dinamis dalam PWA.
Sebagai contoh, pertimbangkan aplikasi perbankan multinasional. Dengan module federation, fitur perbankan inti, platform investasi, dan portal dukungan pelanggan dapat dikembangkan dan di-deploy secara independen. Ini memungkinkan tim khusus untuk fokus pada area tertentu sambil memastikan pengalaman pengguna yang terpadu dan konsisten di semua layanan.
Alternatif untuk Module Federation
Meskipun Module Federation menawarkan solusi yang menarik untuk arsitektur micro-frontend, ini bukan satu-satunya pilihan. Teknik populer lainnya termasuk:
- iFrames: Pendekatan sederhana namun seringkali kurang fleksibel yang menyematkan satu aplikasi di dalam aplikasi lain.
- Web Components: Elemen HTML kustom yang dapat digunakan kembali di berbagai aplikasi.
- Single-SPA: Kerangka kerja untuk membangun aplikasi halaman tunggal dengan beberapa kerangka kerja.
- Integrasi Waktu Build: Menggabungkan semua micro-frontend menjadi satu aplikasi selama proses build.
Setiap teknik memiliki kelebihan dan kekurangan masing-masing, dan pilihan terbaik tergantung pada persyaratan spesifik aplikasi. Module Federation membedakan dirinya dengan fleksibilitas runtime dan kemampuannya untuk berbagi kode secara dinamis tanpa memerlukan pembangunan ulang dan deployment ulang penuh dari semua aplikasi.
Kesimpulan
JavaScript Module Federation adalah teknik yang kuat untuk membangun arsitektur micro-frontend yang skalabel, mudah dipelihara, dan independen. Ini menawarkan banyak manfaat, termasuk deployment independen, peningkatan skalabilitas, peningkatan kemudahan pemeliharaan, agnostik teknologi, dan penggunaan ulang kode. Dengan memahami konsep-konsep utama, mengimplementasikan contoh-contoh praktis, dan mempertimbangkan konsep-konsep lanjutan, pengembang dapat memanfaatkan Module Federation untuk membangun aplikasi web yang kuat dan fleksibel. Seiring aplikasi web terus bertambah kompleks, Module Federation menyediakan alat yang berharga untuk mengelola kompleksitas tersebut dan memungkinkan tim untuk bekerja lebih efisien dan efektif.
Rangkul kekuatan pengembangan web terdesentralisasi dengan JavaScript Module Federation dan buka potensi untuk membangun aplikasi yang benar-benar modular dan skalabel. Baik Anda membangun platform e-commerce, aplikasi perusahaan, atau CMS, Module Federation dapat membantu Anda memecah aplikasi menjadi unit-unit yang lebih kecil, lebih mudah dikelola, dan memberikan pengalaman pengguna yang lebih baik.