Tutustu JavaScript Module Federationiin, mullistavaan tekniikkaan skaalautuvien mikro-frontend-arkkitehtuurien rakentamiseksi. Opi sen hyödyt ja parhaat käytännöt.
JavaScript Module Federation: Kattava opas mikro-frontend-arkkitehtuuriin
Jatkuvasti kehittyvässä web-kehityksen maailmassa suurten ja monimutkaisten sovellusten rakentamisesta voi nopeasti tulla pelottava tehtävä. Perinteiset monoliittiset arkkitehtuurit johtavat usein tiukasti kytkettyihin koodikantoihin, mikä haittaa skaalautuvuutta, ylläpidettävyyttä ja itsenäisiä julkaisuja. Mikro-frontendit tarjoavat houkuttelevan vaihtoehdon, joka jakaa sovelluksen pienempiin, itsenäisesti julkaistaviin yksiköihin. Erilaisten mikro-frontend-tekniikoiden joukosta JavaScript Module Federation erottuu voimakkaana ja eleganttina ratkaisuna.
Mitä on JavaScript Module Federation?
Webpack 5:n esittelemä JavaScript Module Federation antaa JavaScript-sovellusten jakaa koodia ja riippuvuuksia dynaamisesti ajon aikana. Toisin kuin perinteiset koodinjakomenetelmät, jotka perustuvat käännösaikaisiin riippuvuuksiin, Module Federation mahdollistaa sovellusten ladata ja suorittaa koodia muista sovelluksista, vaikka ne olisi rakennettu eri teknologioilla tai saman kirjaston eri versioilla. Tämä luo todella hajautetun ja irrallisen arkkitehtuurin.
Kuvittele tilanne, jossa useat tiimit työskentelevät suuren verkkokauppasivuston eri osien parissa. Yksi tiimi voi olla vastuussa tuotekatalogista, toinen ostoskorista ja kolmas käyttäjien tunnistautumisesta. Module Federationin avulla jokainen tiimi voi kehittää, rakentaa ja julkaista oman mikro-frontendinsa itsenäisesti murehtimatta konflikteista tai riippuvuuksista muiden tiimien kanssa. Pääsovellus ("host") voi sitten dynaamisesti ladata ja renderöidä nämä mikro-frontendit ("remotes") ajon aikana, luoden saumattoman käyttäjäkokemuksen.
Module Federationin avainkäsitteet
- Host: Pääsovellus, joka käyttää ja renderöi etämoduuleita.
- Remote: Itsenäinen sovellus, joka tarjoaa moduuleita muiden sovellusten käytettäväksi.
- Shared Modules: Host- ja remote-sovellusten välillä jaetut riippuvuudet. Tämä välttää päällekkäisyyttä ja varmistaa yhtenäiset versiot koko sovelluksessa.
- Module Federation Plugin: Webpack-lisäosa, joka mahdollistaa Module Federation -toiminnallisuuden.
Module Federationin hyödyt
1. Itsenäiset julkaisut
Jokainen mikro-frontend voidaan julkaista itsenäisesti vaikuttamatta sovelluksen muihin osiin. Tämä mahdollistaa nopeammat julkaisusyklit, pienemmän riskin ja lisää ketteryyttä. Tiimi Berliinissä voi julkaista päivityksiä tuotekatalogiin, kun taas ostoskoritiimi Tokiossa jatkaa itsenäistä työtään omien ominaisuuksiensa parissa. Tämä on merkittävä etu globaalisti hajautetuille tiimeille.
2. Parempi skaalautuvuus
Sovellusta voidaan skaalata horisontaalisesti julkaisemalla jokainen mikro-frontend erillisille palvelimille. Tämä mahdollistaa paremman resurssien käytön ja parantaa suorituskykyä. Esimerkiksi tunnistautumispalvelu, joka on usein suorituskyvyn pullonkaula, voidaan skaalata itsenäisesti käsittelemään kuormitushuippuja.
3. Parempi ylläpidettävyys
Mikro-frontendit ovat pienempiä ja hallittavampia kuin monoliittiset sovellukset, mikä tekee niistä helpompia ylläpitää ja debugata. Jokaisella tiimillä on omistajuus omasta koodikannastaan, mikä antaa heille mahdollisuuden keskittyä omaan erityisosaamisalueeseensa. Kuvittele globaali tiimi, joka on erikoistunut maksuyhdyskäytäviin; he voivat ylläpitää kyseistä mikro-frontendia vaikuttamatta muihin tiimeihin.
4. Teknologiariippumattomuus
Mikro-frontendit voidaan rakentaa käyttämällä eri teknologioita tai viitekehyksiä, mikä antaa tiimeille mahdollisuuden valita parhaat työkalut kuhunkin tehtävään. Yksi mikro-frontend voi olla rakennettu Reactilla, kun taas toinen käyttää Vue.js:ää. Tämä joustavuus on erityisen hyödyllistä, kun integroidaan vanhoja sovelluksia tai kun eri tiimeillä on erilaisia mieltymyksiä tai osaamista.
5. Koodin uudelleenkäytettävyys
Jaettuja moduuleita voidaan uudelleenkäyttää useissa mikro-frontend-sovelluksissa, mikä vähentää koodin päällekkäisyyttä ja parantaa yhtenäisyyttä. Tämä on erityisen hyödyllistä yleisille komponenteille, apufunktioille tai design-järjestelmille. Kuvittele globaalisti yhtenäinen design-järjestelmä, joka on jaettu kaikkien mikro-frontendien kesken, varmistaen yhtenäisen brändikokemuksen.
Module Federationin toteutus: Käytännön esimerkki
Käydään läpi yksinkertaistettu esimerkki Module Federationin toteuttamisesta Webpack 5:n avulla. Luomme kaksi sovellusta: host-sovelluksen ja remote-sovelluksen. Remote-sovellus paljastaa yksinkertaisen komponentin, jota host-sovellus käyttää.
Vaihe 1: Host-sovelluksen määrittäminen
Luo uusi hakemisto host-sovellukselle ja alusta uusi npm-projekti:
mkdir host-app
cd host-app
npm init -y
Asenna Webpack ja sen riippuvuudet:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Luo `webpack.config.js`-tiedosto host-sovelluksen juureen seuraavalla konfiguraatiolla:
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/', // Important for 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']
}
}
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remote@http://localhost:3001/remoteEntry.js',
},
shared: ['react', 'react-dom'],
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Tämä konfiguraatio määrittelee sisääntulopisteen, tulostushakemiston, kehityspalvelimen asetukset ja Module Federation -lisäosan. `remotes`-ominaisuus määrittää remote-sovelluksen `remoteEntry.js`-tiedoston sijainnin. `shared`-ominaisuus määrittelee moduulit, jotka jaetaan host- ja remote-sovellusten välillä. Tässä esimerkissä jaamme 'react' ja 'react-dom'.
Luo `index.html`-tiedosto `public`-hakemistoon:
<!DOCTYPE html>
<html>
<head>
<title>Host Application</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Luo `src`-hakemisto ja sen sisään `index.js`-tiedosto. Tämä tiedosto lataa etäkomponentin ja renderöi sen host-sovelluksessa:
import React from 'react';
import ReactDOM from 'react-dom/client';
import RemoteComponent from 'remoteApp/RemoteComponent';
const App = () => (
<div>
<h1>Host Application</h1>
<p>This is the host application consuming a remote component.</p>
<RemoteComponent />
</div>
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
Asenna babel-loader ja sen esiasetukset
npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react style-loader css-loader
Vaihe 2: Remote-sovelluksen määrittäminen
Luo uusi hakemisto remote-sovellukselle ja alusta uusi npm-projekti:
mkdir remote-app
cd remote-app
npm init -y
Asenna Webpack ja sen riippuvuudet:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Luo `webpack.config.js`-tiedosto remote-sovelluksen juureen seuraavalla konfiguraatiolla:
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/',
},
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',
},
shared: ['react', 'react-dom'],
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Tämä konfiguraatio on samankaltainen kuin host-sovelluksessa, mutta muutamalla keskeisellä erolla. `name`-ominaisuudeksi on asetettu `remote`, ja `exposes`-ominaisuus määrittelee moduulit, jotka paljastetaan muille sovelluksille. Tässä tapauksessa paljastamme `RemoteComponent`-komponentin.
Luo `index.html`-tiedosto `public`-hakemistoon:
<!DOCTYPE html>
<html>
<head>
<title>Remote Application</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Luo `src`-hakemisto ja sen sisään `RemoteComponent.js`-tiedosto. Tämä tiedosto sisältää komponentin, joka paljastetaan host-sovellukselle:
import React from 'react';
const RemoteComponent = () => (
<div style={{ border: '2px solid red', padding: '10px', margin: '10px' }}>
<h2>Remote Component</h2>
<p>This component is loaded from the remote application.</p>
</div>
);
export default RemoteComponent;
Luo `src`-hakemisto ja sen sisään `index.js`-tiedosto. Tämä tiedosto renderöi `RemoteComponent`-komponentin, kun remote-sovellusta ajetaan itsenäisesti (valinnainen):
import React from 'react';
import ReactDOM from 'react-dom/client';
import RemoteComponent from './RemoteComponent';
const App = () => (
<div>
<h1>Remote Application</h1>
<RemoteComponent />
</div>
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
Vaihe 3: Sovellusten ajaminen
Lisää start-skriptit molempiin `package.json`-tiedostoihin:
"scripts": {
"start": "webpack serve"
}
Käynnistä molemmat sovellukset komennolla `npm start`. Avaa selaimesi ja siirry osoitteeseen `http://localhost:3000`. Sinun pitäisi nähdä host-sovelluksen renderöivän etäkomponentin. Etäkomponentilla on punainen reuna, mikä osoittaa, että se on ladattu remote-sovelluksesta.
Edistyneet konseptit ja huomioitavat asiat
1. Versionhallinta ja yhteensopivuus
Kun jaetaan riippuvuuksia mikro-frontendien välillä, on tärkeää ottaa huomioon versionhallinta ja yhteensopivuus. Module Federation tarjoaa mekanismeja versiohaarukoiden määrittämiseen ja konfliktien ratkaisemiseen. Työkalut, kuten semanttinen versiointi (semver), ovat ratkaisevan tärkeitä riippuvuuksien hallinnassa ja yhteensopivuuden varmistamisessa eri mikro-frontendien välillä. Epäonnistuminen versionhallinnassa voi johtaa ajonaikaisiin virheisiin tai odottamattomaan käytökseen, erityisesti monimutkaisissa järjestelmissä, joissa on lukuisia mikro-frontendeja.
2. Tunnistautuminen ja valtuutus
Tunnistautumisen ja valtuutuksen toteuttaminen mikro-frontend-arkkitehtuurissa vaatii huolellista suunnittelua. Yleisiä lähestymistapoja ovat jaetun tunnistautumispalvelun käyttö tai token-pohjaisen tunnistautumisen toteuttaminen. Tietoturva on ensisijaisen tärkeää, ja on olennaista noudattaa parhaita käytäntöjä arkaluonteisten tietojen suojaamiseksi. Esimerkiksi verkkokauppa-alustalla voi olla oma tunnistautumiseen erikoistunut mikro-frontend, joka vastaa käyttäjätietojen vahvistamisesta ennen pääsyn myöntämistä muihin mikro-frontendeihin.
3. Mikro-frontendien välinen kommunikaatio
Mikro-frontendien on usein kommunikoitava keskenään vaihtaakseen dataa tai käynnistääkseen toimintoja. Voidaan käyttää erilaisia kommunikaatiomalleja, kuten tapahtumia, jaettua tilanhallintaa tai suoria API-kutsuja. Oikean kommunikaatiomallin valinta riippuu sovelluksen erityisvaatimuksista. Työkaluja kuten Redux tai Vuex voidaan käyttää jaettuun tilanhallintaan. Mukautettuja tapahtumia voidaan käyttää löyhään kytkentään ja asynkroniseen kommunikaatioon. API-kutsuja voidaan käyttää monimutkaisempiin vuorovaikutuksiin.
4. Suorituskyvyn optimointi
Etämoduulien lataaminen voi vaikuttaa suorituskykyyn, erityisesti jos moduulit ovat suuria tai verkkoyhteys on hidas. Moduulien koon optimointi, koodin jakaminen (code splitting) ja etämoduulien välimuistiin tallentaminen voivat parantaa suorituskykyä. Laiska lataus (lazy loading) moduulien lataaminen vain tarvittaessa on toinen tärkeä optimointitekniikka. Harkitse myös sisällönjakeluverkon (CDN) käyttöä etämoduulien tarjoamiseksi maantieteellisesti lähempänä loppukäyttäjiä, mikä vähentää latenssia.
5. Mikro-frontendien testaus
Mikro-frontendien testaaminen vaatii erilaista lähestymistapaa kuin monoliittisten sovellusten testaaminen. Jokainen mikro-frontend tulisi testata itsenäisesti sekä integraatiossa muiden mikro-frontendien kanssa. Sopimustestausta (contract testing) voidaan käyttää varmistamaan, että mikro-frontendit ovat yhteensopivia keskenään. Yksikkötestit, integraatiotestit ja päästä-päähän-testit ovat kaikki tärkeitä mikro-frontend-arkkitehtuurin laadun varmistamiseksi.
6. Virheidenkäsittely ja valvonta
Vankka virheidenkäsittely ja valvonta ovat ratkaisevan tärkeitä ongelmien tunnistamisessa ja ratkaisemisessa mikro-frontend-arkkitehtuurissa. Keskitetyt loki- ja valvontajärjestelmät voivat tarjota näkemyksiä sovelluksen tilasta ja suorituskyvystä. Työkaluja, kuten Sentry tai New Relic, voidaan käyttää virheiden ja suorituskykymittareiden seurantaan eri mikro-frontendien välillä. Hyvin suunniteltu virheidenkäsittelystrategia voi estää ketjureaktioita ja varmistaa joustavan käyttäjäkokemuksen.
Module Federationin käyttötapauksia
Module Federation soveltuu hyvin monenlaisiin käyttötapauksiin, kuten:
- Suuret verkkokauppa-alustat: Sivuston jakaminen pienempiin, itsenäisesti julkaistaviin yksiköihin tuotekatalogille, ostoskorille, käyttäjien tunnistautumiselle ja kassalle.
- Yrityssovellukset: Monimutkaisten kojelautojen ja portaalien rakentaminen, joissa eri tiimit ovat vastuussa eri osioista.
- Sisällönhallintajärjestelmät (CMS): Antaa kehittäjille mahdollisuuden luoda ja julkaista mukautettuja moduuleita tai lisäosia itsenäisesti.
- Mikropalveluarkkitehtuurit: Frontend-sovellusten integrointi mikropalvelu-backendien kanssa.
- Progressiiviset verkkosovellukset (PWA): Ominaisuuksien dynaaminen lataaminen ja päivittäminen PWA:ssa.
Esimerkiksi, ajatellaan monikansallista pankkisovellusta. Module Federationin avulla ydinpankkitoiminnot, sijoitusalusta ja asiakastukiportaali voidaan kehittää ja julkaista itsenäisesti. Tämä mahdollistaa erikoistuneiden tiimien keskittymisen tietyille alueille samalla varmistaen yhtenäisen ja johdonmukaisen käyttäjäkokemuksen kaikissa palveluissa.
Vaihtoehtoja Module Federationille
Vaikka Module Federation tarjoaa houkuttelevan ratkaisun mikro-frontend-arkkitehtuureille, se ei ole ainoa vaihtoehto. Muita suosittuja tekniikoita ovat:
- iFrame-kehykset: Yksinkertainen, mutta usein vähemmän joustava lähestymistapa, joka upottaa yhden sovelluksen toisen sisään.
- Web Components: Uudelleenkäytettävät mukautetut HTML-elementit, joita voidaan käyttää eri sovelluksissa.
- Single-SPA: Viitekehys yhden sivun sovellusten rakentamiseen useilla eri viitekehyksillä.
- Käännösaikainen integraatio: Kaikkien mikro-frontendien yhdistäminen yhdeksi sovellukseksi käännösprosessin aikana.
Jokaisella tekniikalla on omat etunsa ja haittansa, ja paras valinta riippuu sovelluksen erityisvaatimuksista. Module Federation erottuu ajonaikaisella joustavuudellaan ja kyvyllään jakaa koodia dynaamisesti ilman, että kaikkia sovelluksia tarvitsee kääntää ja julkaista uudelleen.
Yhteenveto
JavaScript Module Federation on tehokas tekniikka skaalautuvien, ylläpidettävien ja itsenäisten mikro-frontend-arkkitehtuurien rakentamiseen. Se tarjoaa lukuisia etuja, kuten itsenäiset julkaisut, paremman skaalautuvuuden, helpomman ylläpidettävyyden, teknologiariippumattomuuden ja koodin uudelleenkäytettävyyden. Ymmärtämällä avainkäsitteet, toteuttamalla käytännön esimerkkejä ja huomioimalla edistyneet konseptit, kehittäjät voivat hyödyntää Module Federationia rakentaakseen vakaita ja joustavia verkkosovelluksia. Kun verkkosovellusten monimutkaisuus kasvaa, Module Federation tarjoaa arvokkaan työkalun tämän monimutkaisuuden hallintaan ja mahdollistaa tiimien tehokkaamman työskentelyn.
Hyödynnä hajautetun web-kehityksen voima JavaScript Module Federationin avulla ja avaa potentiaali todella modulaaristen ja skaalautuvien sovellusten rakentamiseen. Rakensitpa sitten verkkokauppa-alustaa, yrityssovellusta tai CMS-järjestelmää, Module Federation voi auttaa sinua jakamaan sovelluksen pienempiin, hallittavampiin yksiköihin ja tarjoamaan paremman käyttäjäkokemuksen.