Sügavuti minev ülevaade Module Federationist mikro-esiosade jaoks. Õppige, kuidas jagada koodi ja sõltuvusi käitusajal, vähendada paketi suurust ja võimaldada sõltumatuid paigaldusi.
Module Federation: Põhjalik juhend käitusaegseks moodulite jagamiseks mikro-esiosades
Pidevalt arenevas veebiarenduse maastikus oleme näinud olulist arhitektuurilist nihet. Oleme liikunud monoliitsetelt arhitektuuridelt tagarakenduste mikroteenustele, otsides skaleeritavust ja meeskondade autonoomiat. Nüüd on sama revolutsioon muutmas ka esiosa. Mikro-esiosade ajastu on käes ja selle keskmes on võimas tehnoloogia, mis muudab selle kõik praktiliseks: Module Federation.
Mikro-esiosade peamine väljakutse on alati olnud lihtne sõnastada, kuid raske lahendada: kuidas luua ühtne, sidus kasutajakogemus mitmest iseseisvalt paigaldatud rakendusest, tekitamata aeglast, ülepaisutatud ja haldamatut segadust? Kuidas jagada ühist koodi, näiteks komponenditeeke või raamistikke nagu React, tekitamata versioonihalduslikke õudusunenägusid või sundimata koordineeritud väljalaskeid?
See on probleem, mille Module Federation elegantselt lahendab. Webpack 5-s tutvustatud tehnoloogia ei ole lihtsalt järjekordne funktsioon; see on paradigma muutus selles, kuidas me veebirakenduste ehitamisest ja paigaldamisest mõtleme. See põhjalik juhend uurib Module Federationi olemust, põhjuseid ja toimimist, keskendudes selle kõige muutlikumale võimekusele: käitusaegsele moodulite jagamisele.
Lühike meeldetuletus: Mis on mikro-esiosad?
Enne Module Federationi mehaanikasse süvenemist lepime kokku, mida me mikro-esiosade all mõtleme. Kujutage ette suurt e-kaubanduse veebisaiti. Monoliitses maailmas on kogu esiosa – tooteotsing, tooteandmed, ostukorv ja kassa – üks suur rakendus. Muudatus kassas olevale nupule võib nõuda kogu rakenduse testimist ja uuesti paigaldamist.
Mikro-esiosa arhitektuur jagab selle monoliidi ärivaldkondadeks. Teil võib olla:
- Otsingumeeskond, mis vastutab otsinguriba ja tulemuste lehe eest.
- Tootemeeskond, mis vastutab tooteandmete ja soovituste eest.
- Kassameeskond, mis vastutab ostukorvi ja makseprotsessi eest.
Iga meeskond saab oma rakenduse osa iseseisvalt ehitada, testida ja paigaldada. See toob kaasa mitmeid olulisi eeliseid:
- Autonoomsed meeskonnad: Meeskonnad saavad töötada ja väljalaskeid teha oma ajakava järgi, mis kiirendab arendust.
- Sõltumatud paigaldused: Viga soovituste mootoris ei takista kriitilise tähtsusega uuendust maksevoos.
- Tehnoloogiline paindlikkus: Otsingumeeskond võiks kasutada Vue.js-i, samal ajal kui tootemeeskond kasutab Reacti, võimaldades meeskondadel valida oma spetsiifilise valdkonna jaoks parima tööriista (kuigi see nõuab hoolikat haldamist).
Samas tekitab see lähenemine oma väljakutseid, peamiselt seoses jagamise ja järjepidevusega, mis viib meid vanade tegemisviiside juurde.
Vanad viisid koodi jagamiseks (ja miks need ebaõnnestuvad)
Ajalooliselt on meeskonnad proovinud mitmeid meetodeid koodi jagamiseks erinevate esiosa rakenduste vahel, millest igaühel on mikro-esiosa kontekstis olulisi puudusi.
NPM paketid
Kõige tavalisem lähenemine on jagatud komponentide või utiliitide avaldamine versioonitud NPM paketina. Jagatud komponenditeek on klassikaline näide.
- Probleem: See on ehitusaegne sõltuvus. Kui meeskond A uuendab jagatud `Button` komponenti `my-ui-library`-s versioonilt 1.1 versioonile 1.2, ei saa meeskonnad B ja C seda uuendust enne, kui nad käsitsi uuendavad oma `package.json` faili, käivitavad `npm install` ja paigaldavad uuesti kogu oma mikro-esiosa. See tekitab tiheda sidumise ja nullib sõltumatute paigalduste eesmärgi. Samuti viib see sama komponendi mitme versiooni laadimiseni brauseris, paisutades lõplikku paketti.
Monorepod jagatud tööruumidega
Monorepod (kasutades tööriistu nagu Lerna või Yarn/NPM workspaces) hoiavad kõiki mikro-esiosasid ühes hoidlas. See lihtsustab jagatud pakettide haldamist.
- Probleem: Kuigi monorepod aitavad parandada arendajakogemust, ei lahenda need põhilist käitusaegset probleemi. Te toetute endiselt ehitusaegsetele sõltuvustele. Muudatus jagatud teegis nõuab endiselt kõigi seda kasutavate rakenduste uuesti ehitamist ja paigaldamist, et muudatus kajastuks.
Välised skriptid <script>
siltide kaudu
Vanakooli meetod teekide nagu jQuery või React kaasamiseks CDN-ist <script>
sildi kaudu.
- Probleem: See lähenemine on habras ja sellel puudub korralik sõltuvuste haldamise süsteem. See reostab globaalset `window` objekti, mis võib põhjustada konflikte. Versioonihaldus on käsitsi tehtav ja vigaderohke ning puudub puude raputamine (tree-shaking), mis tähendab, et laete terve teegi, isegi kui kasutate sellest ainult ühte väikest funktsiooni.
Kõigil neil meetoditel on üks põhimõtteline viga: nad seovad rakendused ehitusajal. Module Federation murrab selle ahela, luues käitusaegseid sõltuvusi.
Siseneb Module Federation: Paradigma muutus
Module Federation võimaldab JavaScripti rakendusel dünaamiliselt laadida koodi teisest, täiesti eraldiseisvast rakendusest käitusajal. Sisuliselt võimaldab see iseseisvalt paigaldatud rakendustel käituda kasutaja brauseris nii, nagu oleksid nad üks, sidus rakendus.
Mõelge sellest kui API-st, kuid esiosa komponentide jaoks. Üks rakendus saab komponendi "eksponeerida" ja teine rakendus saab seda "tarbida", ilma et see oleks otsese sõltuvusena selle `package.json` failis. Ühendus luuakse reaalajas, brauseris, kui kasutaja seda vajab.
See tähendab, et kui kassameeskond uuendab oma `MiniCart` komponenti ja paigaldab selle, laeb peamine kestrakendus (Shell application), mis kuvab `MiniCart`-i päises, automaatselt uue versiooni järgmisel lehe värskendamisel – ilma et kestrakendust oleks vaja uuesti ehitada või paigaldada. See on mängumuutev.
Module Federationi põhikontseptsioonid
Selle toimimise mõistmiseks peame tutvuma mõne Webpacki konfiguratsioonis määratletud võtmeterminiga.
Host
Host on Webpacki ehitus, mis tarbib käitusajal mooduleid teistest rakendustest. Tavaliselt on see teie peamine rakenduse kest – esimene rakendus, mille kasutaja laeb. Host võib, ja sageli ka teeb, eksponeerida ka oma mooduleid.
Remote
Remote on Webpacki ehitus, mis eksponeerib mooduleid teiste rakenduste tarbimiseks. Toote mikro-esiosa on Remote, mis eksponeerib oma `ProductPage` komponendi.
Tähtis: rakendus võib olla samaaegselt nii Host kui ka Remote.
Eksponeeritud moodulid
Need on konkreetsed failid (`.js`, `.jsx`, `.ts` jne), mille Remote teeb Hostidele tarbimiseks kättesaadavaks. See on selgesõnaline leping; importida saab ainult neid mooduleid, mille olete `exposes` konfiguratsioonis loetlenud.
Jagatud moodulid
Siin toimub sõltuvuste dubleerimise vältimise maagia. See konfiguratsioon võimaldab mitmel iseseisvalt ehitatud rakendusel jagada ühte teegi instantsi. Näiteks kui nii Host kui ka Remote kasutavad Reacti, saate selle konfigureerida `shared` mooduliks. Käitusajal kontrollib Module Federation arukalt, kas ühilduv Reacti versioon on juba laetud. Kui on, kasutab Remote Host'i instantsi omaenda allalaadimise asemel, vältides raamistiku topeltlaadimist.
Näide Webpacki konfiguratsioonist
Vaatame kontseptuaalset `webpack.config.js` faili, et näha neid termineid tegevuses.
Remote rakenduse jaoks (nt `productApp`):
// In productApp's webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
// ... other webpack config
plugins: [
new ModuleFederationPlugin({
name: 'productApp', // A unique name for this remote
filename: 'remoteEntry.js', // The manifest file the host will fetch
exposes: {
'./ProductPage': './src/ProductPage',
},
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
}),
],
};
Host rakenduse jaoks (nt `shellApp`):
// In shellApp's webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
// ... other webpack config
plugins: [
new ModuleFederationPlugin({
name: 'shellApp',
remotes: {
productApp: 'productApp@http://localhost:3001/remoteEntry.js',
},
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
}),
],
};
Kuidas käitusaegne moodulite jagamine tegelikult toimib: Samm-sammuline ülevaade
Jälgime födereeritud mooduli teekonda serverist kasutaja ekraanile.
- Host laeb: Kasutaja navigeerib aadressile `www.ecommerce.com`, mis laeb `shellApp`-i. Brauser laeb alla selle esialgsed HTML- ja JavaScript-paketid.
- `remoteEntry.js` fail: `ModuleFederationPlugin` konfiguratsioon `shellApp`-is teavitab seda `productApp`-ist. Initsialiseerimise osana toob Host `remoteEntry.js` faili määratud URL-ilt (`http://localhost:3001/remoteEntry.js`). See fail on väga väike ja toimib manifesti ehk otsingutabelina, andes Hostile teada, milliseid mooduleid `productApp` eksponeerib ja kuidas neid hankida.
- Dünaamilise impordi käivitamine: `shellApp`-i koodis on dünaamiline import tootelehe laadimiseks, tõenäoliselt kasutades `React.lazy`:
const ProductPage = React.lazy(() => import('productApp/ProductPage'));
- Mooduli lahendamine käitusajal: Webpacki käitusaeg püüab selle `import()` kutse kinni. See tuvastab `productApp`-i födereeritud Remote'ina. See konsulteerib juba allalaaditud `remoteEntry.js` manifestiga, et leida konkreetne JavaScripti tükk (chunk), mis sisaldab `ProductPage` moodulit.
- Komponendi tüki hankimine: Seejärel teeb käitusaeg võrgupäringu, et hankida see konkreetne tükk (nt `_src_ProductPage_js.js`) `productApp`-i serverist.
- Arukas sõltuvuste jagamine: See on ülioluline osa. Enne `ProductPage` koodi käivitamist kontrollib käitusaeg selle sõltuvusi. `ProductPage` vajab Reacti. `shared` konfiguratsioon käsib käitusajal kontrollida, kas Reacti singleton-instants on Hosti skoobis juba saadaval. Kuna `shellApp` on Reacti juba laadinud, annab käitusaeg `ProductPage`-le lihtsalt viite olemasolevale instantsile. Reacti ei laeta uuesti alla. Seejärel käivitatakse `ProductPage` ja renderdatakse see ekraanile.
Käitusaegse jagamise peamised eelised uuesti vaadatuna
Mehhanismi mõistmine teeb eelised kristallselgeks.
Tõeliselt sõltumatud paigaldused
`productApp`-i meeskond saab parandada vea, lisada funktsiooni ja paigaldada oma serveri. Järgmisel korral, kui kasutaja külastab `shellApp`-i ja navigeerib tootelehele, hangivad nad uue, uuendatud komponendi koodi. `shellApp`-i meeskond ei teinud midagi. See on lahtisidumise (decoupling) ülim vorm.
Drastiliselt vähendatud paketi suurus
Ilma Module Federationita, kui viis erinevat mikro-esiosa kasutavad kõik Reacti ja komponenditeeki nagu Material-UI, võib kasutaja need massiivsed teegid alla laadida viis korda. `shared` moodulikonfiguratsiooniga laetakse need alla ainult ühe korra. See toob kaasa tohutu jõudluse paranemise ja kiiremad lehe laadimisajad, eriti keerukate rakenduste puhul.
Suurendatud meeskonna autonoomia ja skaleeritavus
Meeskonnad saavad tõeliselt omada oma valdkonda andmebaasist kasutajaliideseni. See organisatsiooniline skaleerimine võimaldab ettevõtetel kasvatada oma insenerimeeskondi ilma suhtlus- ja koordineerimiskuludeta, mis vaevavad monoliitset arendust.
Vastupidavus ja varuvariandid
Mis juhtub, kui Remote rakendus on maas? Kuna moodulid laetakse dünaamiliselt, saate neid tõrkeid oma koodis elegantselt käsitleda. Kasutades tööriistu nagu Reacti `ErrorBoundary` komponent, saate ebaõnnestunud mooduli laadimise kinni püüda ja kuvada varu-kasutajaliidese (nt „Tooteteenus ei ole hetkel saadaval. Palun proovige hiljem uuesti.“) asemel, et kogu rakendus kokku jookseks.
Inkrementaalne moderniseerimine
Module Federation on võimas tööriist pärandmonoliidist eemaldumiseks. Olemasoleva monoliidi saab konfigureerida Hostiks. Uusi funktsioone saab ehitada eraldiseisvate, kaasaegsete mikro-esiosadena (Remote'idena). Host saab seejärel dünaamiliselt importida ja renderdada neid uusi funktsioone, kägistades järk-järgult vana koodibaasi tükkhaaval, ilma et oleks vaja riskantset „suure paugu“ ümberkirjutamist.
Väljakutsed ja kaalutlused födereeritud maailmas
Module Federation on uskumatult võimas, kuid see ei ole imerohi. Selle arhitektuuri kasutuselevõtt nõuab mitmete väljakutsete hoolikat kaalumist.
Jagatud rakenduse olek
Kui `MiniCart` päises (pärit `checkoutApp`-ist) peab uuendama, kui kasutaja klõpsab `ProductPage`-l (pärit `productApp`-ist) nupule „Lisa ostukorvi“, kuidas nad siis suhtlevad? See on klassikaline mikro-esiosa väljakutse.
- Lahendused: Levinud lähenemiste hulka kuuluvad brauseri sündmuste (nagu Custom Events) kasutamine, `window.localStorage` või `sessionStorage` võimendamine, jagatud olekuhalduse teegi (nagu väike Redux või Zustand pood) eksponeerimine Hostist või tagasikutsete ja andmete edastamine vanemrakendusest allapoole. Oluline on hoida suhtlusleping võimalikult lihtne ja stabiilne.
Versioonihaldus ja rikkuvad muudatused
Mis juhtub, kui `productApp`-i meeskond muudab oma `ProductPage` komponendi propse? Nad võivad selle muudatuse paigaldada ja äkki `shellApp` (mis edastab vanu propse) läheb katki. Module Federationi `shared` konfiguratsioonil on valikud sõltuvuste versioonide mittevastavuse käsitlemiseks (nt nõudes kindlat versiooni), kuid eksponeeritud mooduli enda lepingut tuleb hallata meeskondadevahelise suhtluse ja API versioonihaldusstrateegiate kaudu.
Tööriistad ja arendajakogemus
Kohalik arenduskeskkonna seadistamine võib olla keerulisem. Arendaja, kes töötab `shellApp`-i kallal, võib vajada `productApp`-i ja `checkoutApp`-i kohalikku käivitamist, et näha täielikku kogemust. Seda saab hallata tööriistadega nagu Docker Compose või kohandatud skriptidega, kuid see nõuab esialgset investeeringut arendustegevuse operatsioonidesse (DevOps).
Globaalne stiil ja kasutajakogemuse järjepidevus
Kuidas tagada, et `productApp`-i nupp näeb välja samasugune kui `checkoutApp`-i nupp? Järjepideva disainisüsteemi säilitamine on ülioluline. Strateegiate hulka kuuluvad:
- Jagatud CSS-i utiliiditeek (nagu Tailwind CSS), mis on konfigureeritud igas mikro-esiosas.
- Jagatud `ThemeProvider` komponendi eksponeerimine ühisest kasutajaliidese mikro-esiosast.
- CSS-i kohandatud omaduste (muutujate) kasutamine, mis on määratletud Hosti juurtasandil, et tagada järjepidev teema (värvid, fondid, vahed).
Kokkuvõte: Tulevik on födereeritud
Module Federation kujutab endast fundamentaalset hüpet edasi esiosa arhitektuuris. See lahendab otse suuremahuliste, hajutatud veebirakenduste ehitamise põhiprobleemid, pakkudes robustset, brauseripõhist lahendust käitusaegseks koodi jagamiseks.
Viies sõltuvused ehitusajalt käitusajale, avab see tõeliselt sõltumatud paigaldused, parandab jõudlust, kõrvaldades tarnijakoodi dubleerimise, ja annab meeskondadele volituse töötada iseseisvalt. Kuigi see toob kaasa uusi keerukusi seoses olekuhalduse ja liideselepingutega, on selle eelised suurte, pikaealiste rakenduste jaoks vaieldamatud.
Kuna organisatsioonid jätkavad oma digitaalsete toodete ja insenerimeeskondade skaleerimist, muutuvad standardiks arhitektuurid, mis edendavad lahtisidumist, autonoomiat ja tõhusust. Module Federation ei ole enam niši- ega eksperimentaalne tehnoloogia; see on alustala järgmise põlvkonna vastupidavate, skaleeritavate ja hooldatavate mikro-esiosa rakenduste ehitamiseks.