Koodijagamine nurgas või kuidas komponente laiskade moodulite vahel jagada

See artikkel annab teile parema ülevaate, kuidas nurgeline kood teie tükkideks jaotab.

Kui te kardate ülaltoodud nurga CLI väljundit või kui olete uudishimulik, kuidas see koodide jagamine tegelikult toimub, on see postitus teie jaoks.

Koodi tükeldamine võimaldab teil jagada oma koodi erinevateks kimpudeks, mida saab seejärel nõudmise korral laadida. Õige kasutamise korral võib see laadimisaega oluliselt mõjutada.

Sisu

  1. Miks ma peaksin hoolima?
  2. Nurga CLI-koodi poolitus kapoti all
  3. Lihtne nurkne rakendus laiskade moodulitega
  4. Kuidas komponente laiskade moodulite vahel jagada
  5. Järeldus

Miks ma peaksin hoolima?

Kujutame ette, et alustasite uhiuut projekti Nurga all. Te olete lugenud palju ressursse nurkrakenduse arhitektuuri kohta, milline on sobiv kaustastruktuur ja mis kõige tähtsam, kuidas säilitada hea käivitusvõime.

Valisite nurga CLI ja lõite moodulrakenduse, milles on palju laiska laadimisega funktsioonimooduleid. Ja loomulikult lõite ühise mooduli, kuhu panite tavaliselt kasutatavad direktiivid, torud ja komponendid.

Mõne aja pärast tabasite end mõttelt, et kui teie uus funktsioonimoodul nõuab mõningaid funktsioone teistelt funktsioonimoodulitelt, liigutate selle funktsiooni sellesse ühte jagatud moodulisse.

Rakendus areneb ja varsti märkasite, et selle käivitamise aeg ei vasta teie (ja mis kõige tähtsam, teie kliendi) ootustele.

Nüüd kahtlete ...

  • Kui ma panen kõik oma torud, käskkirjad ja ühised komponendid ühte suurde ühiskasutatavasse moodulisse ja impordin selle laisalt laetud moodulitesse (kus ma kasutan ainult ühte või kahte imporditud funktsiooni), võib see tõenäoliselt põhjustada väljundfailides kasutamata koodi duplikaate .
  • Teisest küljest, kui jagan jagatud funktsioonid mitme jagatud mooduli vahel ja impordin igas konkreetses moodulis ainult need, mida see vajab, vähendab see minu rakenduse suurust? Või Nurga all tehakse kõik sellised optimeerimised vaikimisi?

Demüsifitseerime!

Nurga CLI-koodi poolitus kapoti all

Nagu me kõik teame, kasutab praegune nurk-CLI-versioon komplekteerimiseks veebipaketti. Kuid vaatamata sellele vastutab veebipakett ka koodide jagamise eest.

Vaatame siis, kuidas veebipakett seda teeb.

Webpack 4 tutvustas SplitChunksPlugin'i, mis võimaldab meil määratleda heuristika moodulite tükkideks jagamiseks. Paljud inimesed kurdavad, et see konfiguratsioon tundub salapärane. Ja samal ajal on see koodide jagamise kõige huvitavam osa.

Kuid enne SplitChunksPlugini optimeerimise rakendamist loob veebipakk uue tüki:

  • iga sisenemispunkti jaoks

Nurga CLI konfigureerib järgmised sisenemispunktid

peamised polütäidete stiilid

mille tulemuseks on samade nimedega tükid.

  • iga dünaamiliselt laaditud mooduli jaoks (kasutades süntaksit import (), mis vastab ECMAScripti dünaamilise impordi ettepanekule)

Kas mäletate lastLaste süntaksit? See on signaal veebipakki tüki loomiseks.

Nüüd liigume edasi SplitChunksPlugini juurde. Selle saab lubada veebipack.config.js optimeerimisplokis

Vaatame nurga CLI lähtekoodi ja leiame selle konfiguratsiooniosa:

SplitChunksPlugini konfiguratsioon nurga CLI 8 korral

Keskendume siin vahemägirühmade võimalustele, kuna see on veebipaketi “retsept”, kuidas luua eraldatud tükke teatud tingimuste põhjal.

cacheGroups on tavaline objekt, kus võti on rühma nimi. Põhimõtteliselt võime vahemälurühma mõelda kui potentsiaalset võimalust uue osa loomiseks.

Igal rühmal on palju konfiguratsioone ja nad saavad konfiguratsiooni pärida splitChunksi tasemel.

Vaatame üle need võimalused, mida nägime ülal nurga CLI konfiguratsioonis:

  • tükkide väärtust saab kasutada moodulite filtreerimiseks sünkroonimise ja asünkri tükkide vahel. Selle väärtus võib olla algne, asünkrooniline või kogu. algne tähendab failide lisamist tükile ainult siis, kui need imporditakse sünkroonimispakettidesse. async tähendab failide lisamist tükile ainult siis, kui need imporditakse asünkri tükkidesse (async vaikimisi)
  • minChunks käsib webpackil süstida mooduleid tükkideks ainult siis, kui neid on jagatud vähemalt kahe tüki vahel (vaikimisi 1)
  • nimi käsib webpackil seda nime kasutada äsja loodud tüki jaoks. Stringi või funktsiooni määramisel, mis tagastab alati sama stringi, liidetakse kõik tavalised moodulid ühte tükki.
  • prioriteediväärtust kasutatakse kõige paremini sobitatud tükkide tuvastamiseks, kui moodul kuulub paljude tükkide rühma.
  • jõustamine käsib webpackil ignoreerida valikuid minSize, minChunks, maxAsyncRequests ja maxInitialRequests ning luua selle vahemälurühma jaoks alati tükke. Siin on üks väike getcha: kui mõni neist ignoreeritud suvanditest on olemas cacheGroupi tasemel, kasutatakse seda võimalust ikkagi.
  • testib, millised moodulid see vahemälurühm valib. Nagu võis märgata, kasutab nurk-CLI seda suvandit, et teisaldada kõik sõlmede_moodulite sõltuvused müüja tüki.
  • MinSize kasutatakse genereeritava tüki minimaalse suuruse määramiseks baitides. See ei ilmunud nurga CLI konfiguratsioonis, kuid see on väga oluline variant, millest peaksime olema teadlikud. (Nagu lähtekood väidab, on see tootmises vaikimisi 30 kb ja arenduskeskkonnas 10 kb)
Näpunäide: hoolimata asjaolust, et veebipaketi dokumendid määratlevad vaikeseaded, viitan täpsete väärtuste leidmiseks veebipaketi lähtekoodile

Vaatame siin järgmist: Nurga CLI teisaldab mooduli aadressile:

  • hankija tükk, kui see moodul tuleb kataloogist node_modules.
  • vaikimisi tükk, kui see moodul imporditakse asünkomoodulisse ja jagatakse vähemalt kahe mooduli vahel. Pange tähele, et siin on võimalik kasutada paljusid vaikimisi tükke. Selgitan, kuidas webpack nendele tükkidele nimesid genereerib.
  • tavaline tükk, kui see moodul imporditakse asünkomooduli sisse ja jagatakse vähemalt kahe mooduli vahel ning see ei kuulunud vaikimisi pakki (tere prioriteet) ja ka siis, kui see on (tänu theenforce suvandile)

Aitab teooriast, praktiseerime.

Lihtne nurkne rakendus laiskmoodulitega

SplitChunksPlugini protsessi selgitamiseks alustame nurgarakenduse lihtsustatud versiooniga:

rakendus (a (laisk) └── .com a.component.ts └── └── a.module.ts │ ab │ └── ab.component.ts │ └── ab.module.ts │ ├── b (laisad) └── b.component.ts │ └── b.module.ts │ └── c (laisad) └── └── c.component.ts └── └── c.module. ts │ └── cd │ └── cd.component.ts │ └── cd.module.ts │ └── d (lazy) │ └── d.component.ts │ └── d.module.ts └── jagatud │ └── shared.module.ts └── └── app.component.ts └── app.module.ts

Siin on a, b, c ja d laisad moodulid, mis tähendab, et nad imporditakse, kasutades süntaksit import ().

komponendid a ja b kasutavad mallides ab-komponenti. c ja d komponendid kasutavad cd komponenti.

Nurga moodulite sõltuvused

Erinevus ab.module ja cd.module vahel seisneb selles, et ab.module imporditakse a.module ja b.module ning cd.module imporditakse jagatud moodulis.

See struktuur kirjeldab täpselt kahtlusi, mida me tahtsime demüstifitseerida. Selgitame välja, kus ab- ja cd-moodulid lõppväljundis asuvad.

Algoritm

1) SplitChunksPlugini algoritm algab iga varem loodud tüki indeksi andmisega.

tükid indeksi järgi

2) Seejärel suletakse see kõigi kompileerimise moodulitega, et täita chunkSetsInGraph Map. See sõnastik näitab, millised tükid jagavad sama koodi.

chunkSetsInGraph

Nt 1,2 peamist, polütäidise rida tähendab, et on vähemalt üks moodul, mis ilmub kahes tükis: põhi- ja polütäidisena.

a ja b moodulitel on sama kood fromab-moodulil, nii et võime märgata ka ülaltoodud kombinatsiooni (4,5).

3) Kõndige kõik moodulid läbi ja mõelge, kas konkreetsele vahemägirühmale on võimalik luua uus tükk.

3a) Kõigepealt teeb webpack kindlaks, kas mooduli saab lisada konkreetsele cacheGroupile, kontrollides atribuuti ccacheGroup.test.

ab.mooduli testid

vaikimisi test määratlemata => ok
tavaline test määratlemata => ok
müüja testfunktsioon => vale

vaikimisi ja tavaline vahemälurühm ei määratlenud kõige paremat atribuuti, nii et see peaks selle läbima. tarnija vahemälurühm määratleb funktsiooni, kus on olemas filter, mis hõlmab ainult mooduleid rajalt thenode_modules.

cd.mooduli testid on samad.

3b) Nüüd on aeg läbi käia kõik tükkide kombinatsioonid.

Iga moodul saab aru, millistes tükkides see ilmub (tänu moodulile.chunksIterable atribuut).

ab.module imporditakse kaheks laisaks tükiks. Seega on selle kombinatsioonid (4), (5) ja (4,5).

Teisest küljest imporditakse cd.module ainult jagatud moodulis, mis tähendab, et see imporditakse ainult põhiosa. Selle kombinatsioone on ainult (1).

Seejärel plugin filtreerib kombinatsioonid minChunk suuruse järgi:

if (chunkCombination.size 

Kuna ab.moodulil on kombinatsioon (4,5), peaks see kontroll läbima. Seda me cd.module kohta öelda ei saa. Sel hetkel jääb see moodul elama põhiosa sisse.

3c) On veel üks kontroll cacheGroup.chunkds poolt (algne, asünkrooniline või kõik)

ab.module imporditakse asünkroonide (laisalt laaditud) tükkidesse. See on täpselt see, mida vaike- ja tavalised vahemälurühmad vajavad. Nii lisatakse ab.module kahele uuele võimalikule tükile (vaikimisi ja tavalised).

Ma lubasin seda varem, nii et siin me läheme.

Kuidas genereerib webpack SplitChunksPlugini loodud tüki nime?

Selle lihtsustatud versiooni saab esitada kujul

kus:

  • groupName on rühma nimi (meie puhul vaikimisi)
  • ~ on defaultAutomaticNameDelimiter
  • chunkNames viitab kõigi sellesse rühma kuuluvate tükkide nimede loendile. See nimi on nagu fullPathi tee, kuid kaldkriipsu asemel kasutab see -.

Nt dd-moodul tähendab, et meil on d-moodulis fail kaustas d.

Seega, kui kasutasime importi ('./a / a.module') ja importi ('./b / b.module'), saame

Osa vaikenime struktuur

Veel üks mainimist väärt asi on see, et kui tüki nime pikkus ulatub 109 tähemärgini, lõikab veebipakk selle lahti ja lisab selle lõpus räsi.

Suure tüki nime struktuur, mis jagab koodi mitme laisa mooduli vahel

Oleme valmis täitma faili chunksInfoMap, mis teab kõike võimalikest uutest tükkidest ja teab ka seda, millistest moodulitest see peaks koosnema, ja seotud tükkidest, kus need moodulid praegu asuvad.

chunksInfoMap

On aeg filtrida võimalikud tükid

SplitChunksPlugin silub chunksInfoMap'i üksusi üle, et leida parim sobiv kirje. Mida see tähendab?

Vaikimisi vahemälurühmal on prioriteet 10, mis ületab ühist (ainult 5). See tähendab, et vaikimisi sobib kõige paremini kirje ja seda tuleks kõigepealt töödelda.

Kui kõik muud nõuded on täidetud, eemaldab webpack chunksInfoMap'i sõnastikus kõik tükkide moodulid muudest võimalikest tükkidest. Kui moodulit pole alles, siis see moodul kustutatakse

Sel moel on vaikimisi ~ aa-moodul ~ bb-moodul ülimuslik tavalise tüki suhtes. Viimane eemaldatakse, kuna see sisaldab sama moodulite loendit.

Viimane, kuid mitte vähem tähtis samm on teha mõned optimeerimised (näiteks eemaldada dubleerimised) ja veenduda, et kõik nõuded, näiteks maxSize, on täidetud.

SplitChunksPlugini kogu lähtekoodi leiate siit

Oleme avastanud, et veebipakk loob tükke kolmel erineval viisil:

  • iga sissekande kohta
  • dünaamiliselt laaditud moodulite jaoks
  • jagatud koodi jaoks SplitChunksPlugini abiga
Nurga CLI väljund tükkide kaupa

Läheme nüüd tagasi oma kahtluste juurde, mis on parim viis jagatud koodi hoidmiseks.

Kuidas komponente laiskade moodulite vahel jagada

Nagu nägime oma lihtsas nurgarakenduses, lõi webpack ab.module jaoks eraldi tüki, kuid sisaldas peamises osas cd.module.

Võtame kokku selle postituse peamised võtmised:

  • Kui paneme kõik jagatud torud, direktiivid ja ühised komponendid ühte suurde ühiskasutatavasse moodulisse ja impordime selle kõikjale (sünkroonimise ja asünkri tükkide sees), siis on see kood meie algses peamises tükis. Nii et kui soovite saada esialgset koormust halvasti, on see tee minna.
  • Teisest küljest, kui jagame tavaliselt kasutatava koodi laiskade laaditud moodulite vahel, luuakse uus jagatud osa ja see laaditakse ainult siis, kui mõni neist laiskadest moodulitest on laaditud. See peaks parandama rakenduse esialgset koormust. Kuid tehke seda arukalt, sest mõnikord on parem panna väike kood ühte tüki, kui eraldi tüki jaoks vajaliku lisanõude olemasolu.

Järeldus

Loodan, et peaksite nüüd nurga CLI väljundit selgelt mõistma ja SplitChunksPlugini tükkide abil eristama sisenemist, dünaamilist ja poolitatud.

Head kodeerimist!