Susipažinkite su JavaScript modulių federacija – revoliucine technika, skirta kurti mastelio keitimui pritaikytas ir lengvai prižiūrimas mikro-frontend architektūras.
JavaScript modulių federacija: išsamus mikro-frontend architektūros vadovas
Nuolat besikeičiančiame interneto svetainių kūrimo pasaulyje didelių, sudėtingų programų kūrimas gali greitai tapti bauginančia užduotimi. Tradicinės monolitinės architektūros dažnai sukuria glaudžiai susietas kodo bazes, o tai trukdo mastelio keitimui, priežiūrai ir nepriklausomam diegimui. Mikro-frontend architektūros siūlo patrauklią alternatyvą, suskaidydamos programą į mažesnius, nepriklausomai diegiamus vienetus. Tarp įvairių mikro-frontend technikų, JavaScript modulių federacija išsiskiria kaip galingas ir elegantiškas sprendimas.
Kas yra JavaScript modulių federacija?
JavaScript modulių federacija, pristatyta kartu su Webpack 5, leidžia JavaScript programoms dinamiškai dalintis kodu ir priklausomybėmis vykdymo metu. Skirtingai nuo tradicinių kodo dalinimosi metodų, kurie priklauso nuo priklausomybių kūrimo (build) etape, modulių federacija leidžia programoms įkelti ir vykdyti kodą iš kitų programų, net jei jos buvo sukurtos naudojant skirtingas technologijas ar tos pačios bibliotekos versijas. Tai sukuria išties paskirstytą ir atsietą architektūrą.
Įsivaizduokite scenarijų, kai kelios komandos dirba su skirtingomis didelės el. prekybos svetainės dalimis. Viena komanda gali būti atsakinga už produktų katalogą, kita – už pirkinių krepšelį, o trečia – už vartotojų autentifikavimą. Su modulių federacija kiekviena komanda gali kurti, kompiliuoti ir diegti savo mikro-frontend'ą nepriklausomai, nesijaudindama dėl konfliktų ar priklausomybių su kitomis komandomis. Pagrindinė programa („priimančioji“ arba „host“) gali dinamiškai įkelti ir atvaizduoti šiuos mikro-frontend'us („nuotolinius“ arba „remotes“) vykdymo metu, sukurdama vientisą vartotojo patirtį.
Pagrindinės modulių federacijos sąvokos
- Priimančioji programa (Host): Pagrindinė programa, kuri naudoja ir atvaizduoja nuotolinius modulius.
- Nuotolinė programa (Remote): Nepriklausoma programa, kuri pateikia modulius, skirtus naudoti kitoms programoms.
- Bendrinami moduliai (Shared Modules): Priklausomybės, kurios yra bendros tarp priimančiosios ir nuotolinių programų. Tai padeda išvengti dubliavimo ir užtikrina nuoseklias versijas visoje programoje.
- Modulių federacijos įskiepis (Module Federation Plugin): Webpack įskiepis, kuris įgalina modulių federacijos funkcionalumą.
Modulių federacijos privalumai
1. Nepriklausomi diegimai
Kiekvienas mikro-frontend gali būti diegiamas nepriklausomai, nepaveikiant kitų programos dalių. Tai leidžia greičiau išleisti naujas versijas, sumažina riziką ir padidina lankstumą. Komanda Berlyne gali diegti produktų katalogo atnaujinimus, kol pirkinių krepšelio komanda Tokijuje toliau savarankiškai dirba su savo funkcijomis. Tai yra didelis pranašumas visame pasaulyje paskirstytoms komandoms.
2. Padidintas mastelio keitimo lankstumas
Programos mastelį galima keisti horizontaliai, diegiant kiekvieną mikro-frontend'ą atskiruose serveriuose. Tai leidžia geriau išnaudoti išteklius ir pagerinti našumą. Pavyzdžiui, autentifikavimo paslauga, kuri dažnai tampa našumo kliūtimi, gali būti keičiamo mastelio nepriklausomai, kad atlaikytų didžiausias apkrovas.
3. Pagerinta priežiūra
Mikro-frontend'ai yra mažesni ir lengviau valdomi nei monolitinės programos, todėl juos lengviau prižiūrėti ir derinti. Kiekviena komanda valdo savo kodo bazę, todėl gali sutelkti dėmesį į savo konkrečią kompetencijos sritį. Įsivaizduokite globalią komandą, besispecializuojančią mokėjimo sistemų srityje; ji gali prižiūrėti tą konkretų mikro-frontend'ą, nepaveikdama kitų komandų.
4. Technologinis agnostiškumas
Mikro-frontend'ai gali būti kuriami naudojant skirtingas technologijas ar karkasus, leidžiant komandoms pasirinkti geriausius įrankius darbui. Vienas mikro-frontend'as gali būti sukurtas su React, o kitas – su Vue.js. Šis lankstumas ypač naudingas integruojant senas programas arba kai skirtingos komandos turi skirtingus pageidavimus ar kompetencijas.
5. Kodo pakartotinis naudojimas
Bendrinami moduliai gali būti naudojami pakartotinai keliuose mikro-frontend'uose, mažinant kodo dubliavimą ir gerinant nuoseklumą. Tai ypač naudinga bendriems komponentams, pagalbinių funkcijų bibliotekoms ar dizaino sistemoms. Įsivaizduokite visame pasaulyje nuoseklią dizaino sistemą, bendrinamą visuose mikro-frontend'uose, užtikrinančią vieningą prekės ženklo patirtį.
Modulių federacijos diegimas: praktinis pavyzdys
Panagrinėkime supaprastintą pavyzdį, kaip įdiegti modulių federaciją naudojant Webpack 5. Sukursime dvi programas: priimančiąją (host) programą ir nuotolinę (remote) programą. Nuotolinė programa pateiks paprastą komponentą, kurį naudos priimančioji programa.
1 Žingsnis: Priimančiosios programos paruošimas
Sukurkite naują katalogą priimančiajai programai ir inicializuokite naują npm projektą:
mkdir host-app
cd host-app
npm init -y
Įdiekite Webpack ir jo priklausomybes:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Sukurkite `webpack.config.js` failą priimančiosios programos šakniniame kataloge su tokia konfigūracija:
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$/_vx, // Updated regex to include JSX
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'] // Added react preset
}
}
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remote@http://localhost:3001/remoteEntry.js', // Pointing to the remote entry
},
shared: ['react', 'react-dom'], // Share react
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Ši konfigūracija apibrėžia įvesties tašką, išvesties katalogą, kūrimo serverio nustatymus ir modulių federacijos įskiepį. Savybė `remotes` nurodo nuotolinės programos `remoteEntry.js` failo vietą. Savybė `shared` apibrėžia modulius, kurie yra bendrinami tarp priimančiosios ir nuotolinės programų. Šiame pavyzdyje mes bendriname 'react' ir 'react-dom'.
Sukurkite `index.html` failą `public` kataloge:
<!DOCTYPE html>
<html>
<head>
<title>Host Application</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Sukurkite `src` katalogą ir jame `index.js` failą. Šis failas įkels nuotolinį komponentą ir jį atvaizduos priimančiojoje programoje:
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/>);
Įdiekite babel-loader ir jo išankstinius nustatymus:
npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react style-loader css-loader
2 Žingsnis: Nuotolinės programos paruošimas
Sukurkite naują katalogą nuotolinei programai ir inicializuokite naują npm projektą:
mkdir remote-app
cd remote-app
npm init -y
Įdiekite Webpack ir jo priklausomybes:
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
Sukurkite `webpack.config.js` failą nuotolinės programos šakniniame kataloge su tokia konfigūracija:
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/', // Important for Module Federation
},
devServer: {
port: 3001,
hot: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/, // Updated regex to include JSX
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', // Exposing the component
},
shared: ['react', 'react-dom'], // Share react
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
Ši konfigūracija yra panaši į priimančiosios programos, tačiau su keliais esminiais skirtumais. Savybė `name` nustatyta į `remote`, o savybė `exposes` apibrėžia modulius, kurie yra pateikiami kitoms programoms. Šiuo atveju mes pateikiame `RemoteComponent`.
Sukurkite `index.html` failą `public` kataloge:
<!DOCTYPE html>
<html>
<head>
<title>Remote Application</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
Sukurkite `src` katalogą ir jame `RemoteComponent.js` failą. Šiame faile bus komponentas, kuris yra pateikiamas priimančiajai programai:
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;
Sukurkite `src` katalogą ir jame `index.js` failą. Šis failas atvaizduos `RemoteComponent`, kai nuotolinė programa bus paleista atskirai (nebūtina):
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/>);
3 Žingsnis: Programų paleidimas
Pridėkite paleidimo scenarijus (scripts) į abu `package.json` failus:
"scripts": {
"start": "webpack serve"
}
Paleiskite abi programas naudodami `npm start`. Atidarykite naršyklę ir eikite į `http://localhost:3000`. Turėtumėte pamatyti priimančiąją programą, atvaizduojančią nuotolinį komponentą. Nuotolinis komponentas turės raudoną rėmelį, rodantį, kad jis įkeltas iš nuotolinės programos.
Pažangios koncepcijos ir svarstymai
1. Versijavimas ir suderinamumas
Dalijantis priklausomybėmis tarp mikro-frontend'ų, svarbu atsižvelgti į versijavimą ir suderinamumą. Modulių federacija suteikia mechanizmus, leidžiančius nurodyti versijų diapazonus ir spręsti konfliktus. Įrankiai, tokie kaip semantinis versijavimas (semver), tampa itin svarbūs valdant priklausomybes ir užtikrinant suderinamumą tarp skirtingų mikro-frontend'ų. Netinkamai valdomas versijavimas gali sukelti vykdymo laiko klaidas ar netikėtą elgesį, ypač sudėtingose sistemose su daugybe mikro-frontend'ų.
2. Autentifikavimas ir autorizavimas
Autentifikavimo ir autorizavimo įgyvendinimas mikro-frontend architektūroje reikalauja kruopštaus planavimo. Įprasti metodai apima bendros autentifikavimo paslaugos naudojimą arba prieigos raktais (token-based) pagrįstą autentifikavimą. Saugumas yra svarbiausias prioritetas, todėl būtina laikytis geriausių praktikų siekiant apsaugoti jautrius duomenis. Pavyzdžiui, el. prekybos platforma gali turėti specialų autentifikavimo mikro-frontend'ą, atsakingą už vartotojo kredencialų patikrinimą prieš suteikiant prieigą prie kitų mikro-frontend'ų.
3. Komunikacija tarp mikro-frontend'ų
Mikro-frontend'ams dažnai reikia bendrauti tarpusavyje, kad keistųsi duomenimis ar inicijuotų veiksmus. Galima naudoti įvairius komunikacijos modelius, tokius kaip įvykiai (events), bendras būsenos valdymas (shared state management) ar tiesioginiai API iškvietimai. Tinkamo komunikacijos modelio pasirinkimas priklauso nuo konkrečių programos reikalavimų. Įrankiai, tokie kaip Redux ar Vuex, gali būti naudojami bendram būsenos valdymui. Individualizuoti įvykiai gali būti naudojami silpnam susiejimui ir asinchroninei komunikacijai. API iškvietimai gali būti naudojami sudėtingesnėms sąveikoms.
4. Našumo optimizavimas
Nuotolinių modulių įkėlimas gali paveikti našumą, ypač jei moduliai yra dideli arba tinklo ryšys lėtas. Modulių dydžio optimizavimas, kodo skaidymas (code splitting) ir nuotolinių modulių talpinimas podėlyje (caching) gali pagerinti našumą. Atidėtasis įkėlimas (Lazy loading), kai moduliai įkeliami tik tada, kai jų prireikia, yra dar viena svarbi optimizavimo technika. Taip pat apsvarstykite galimybę naudoti turinio pristatymo tinklą (CDN), kad nuotoliniai moduliai būtų pateikiami iš geografiškai artimesnių vietų galutiniams vartotojams, taip sumažinant delsą.
5. Mikro-frontend'ų testavimas
Mikro-frontend'ų testavimas reikalauja kitokio požiūrio nei monolitinių programų testavimas. Kiekvienas mikro-frontend'as turėtų būti testuojamas atskirai, taip pat ir integracijoje su kitais mikro-frontend'ais. Sutarties testavimas (Contract testing) gali būti naudojamas siekiant užtikrinti, kad mikro-frontend'ai yra suderinami tarpusavyje. Vienetiniai testai, integracijos testai ir ištisiniai (end-to-end) testai yra svarbūs norint užtikrinti mikro-frontend architektūros kokybę.
6. Klaidų tvarkymas ir stebėsena
Tvirto klaidų tvarkymo ir stebėsenos įgyvendinimas yra labai svarbus norint nustatyti ir išspręsti problemas mikro-frontend architektūroje. Centralizuotos registravimo ir stebėjimo sistemos gali suteikti įžvalgų apie programos būklę ir našumą. Įrankiai, tokie kaip Sentry ar New Relic, gali būti naudojami klaidų ir našumo metrikų stebėjimui skirtinguose mikro-frontend'uose. Gerai suprojektuota klaidų tvarkymo strategija gali užkirsti kelią grandininėms gedimams ir užtikrinti atsparią vartotojo patirtį.
Modulių federacijos naudojimo atvejai
Modulių federacija puikiai tinka įvairiems naudojimo atvejams, įskaitant:
- Didelės el. prekybos platformos: Svetainės suskaidymas į mažesnius, nepriklausomai diegiamus vienetus produktų katalogui, pirkinių krepšeliui, vartotojų autentifikavimui ir atsiskaitymui.
- Įmonių programos: Sudėtingų prietaisų skydelių ir portalų kūrimas, kai skirtingos komandos yra atsakingos už skirtingas sritis.
- Turinio valdymo sistemos (TVS): Leidimas kūrėjams savarankiškai kurti ir diegti pasirinktinius modulius ar įskiepius.
- Mikropaslaugų architektūros: Frontend programų integravimas su mikropaslaugų backend'ais.
- Progresyviosios žiniatinklio programos (PWA): Dinamiškas funkcijų įkėlimas ir atnaujinimas PWA programoje.
Pavyzdžiui, įsivaizduokite tarptautinę bankininkystės programą. Naudojant modulių federaciją, pagrindinės bankininkystės funkcijos, investavimo platforma ir klientų aptarnavimo portalas gali būti kuriami ir diegiami nepriklausomai. Tai leidžia specializuotoms komandoms sutelkti dėmesį į konkrečias sritis, tuo pačiu užtikrinant vieningą ir nuoseklią vartotojo patirtį visose paslaugose.
Alternatyvos modulių federacijai
Nors modulių federacija siūlo patrauklų sprendimą mikro-frontend architektūroms, tai nėra vienintelis variantas. Kitos populiarios technikos apima:
- iFrames: Paprastas, bet dažnai mažiau lankstus metodas, kuris įterpia vieną programą į kitą.
- Web Components: Pakartotinai naudojami pasirinktiniai HTML elementai, kuriuos galima naudoti skirtingose programose.
- Single-SPA: Karkasas, skirtas kurti vieno puslapio programas (SPA) su keliais karkasais.
- Integracija kūrimo (build) etape: Visų mikro-frontend'ų sujungimas į vieną programą kūrimo proceso metu.
Kiekviena technika turi savo privalumų ir trūkumų, o geriausias pasirinkimas priklauso nuo konkrečių programos reikalavimų. Modulių federacija išsiskiria savo lankstumu vykdymo metu ir gebėjimu dinamiškai dalintis kodu, nereikalaujant visų programų perkompiliavimo ir pakartotinio diegimo.
Išvada
JavaScript modulių federacija yra galinga technika, skirta kurti mastelio keitimui pritaikytas, lengvai prižiūrimas ir nepriklausomas mikro-frontend architektūras. Ji siūlo daugybę privalumų, įskaitant nepriklausomus diegimus, padidintą mastelio keitimo lankstumą, pagerintą priežiūrą, technologinį agnostiškumą ir kodo pakartotinį naudojimą. Suprasdami pagrindines sąvokas, įgyvendindami praktinius pavyzdžius ir atsižvelgdami į pažangias koncepcijas, kūrėjai gali pasinaudoti modulių federacija kurdami tvirtas ir lanksčias interneto programas. Kadangi interneto programos tampa vis sudėtingesnės, modulių federacija suteikia vertingą įrankį šiam sudėtingumui valdyti ir leidžia komandoms dirbti efektyviau.
Pasinaudokite decentralizuoto interneto svetainių kūrimo galia su JavaScript modulių federacija ir atverkite potencialą kurti išties modulines ir mastelio keitimui pritaikytas programas. Nesvarbu, ar kuriate el. prekybos platformą, įmonės programą, ar TVS, modulių federacija gali padėti jums suskaidyti programą į mažesnius, lengviau valdomus vienetus ir suteikti geresnę vartotojo patirtį.