AngularJS: `malli` vs` templateUrl`

Muutaman viime kuukauden aikana olen etsinyt erilaisia ​​tapoja parantaa suorituskykyä jättiläisellä SPA: lla, jolla työskentelen Domossa. Olemme edistyneet vakavasti, mutta miljoonan rivin kanssa yhdessä kylpylässä jotkut muutokset eivät ole aina helppoja. Yksi tiimimme jäsenistä teki löytön auttaakseen lisäämään lazyloading-arvoa AngularJS-projekteihin, ja olemme panostaneet siihen voimakkaasti. Muutama ryhmän jäsen (Jason ja Tim) auttaa meitä mittaamaan aikaa, joka kuluu sovelluksemme alustamiseen. Olemme myös käyttäneet webpackia rakenteen virtaviivaistamiseen ja joidenkin käyttämiesi kuvioiden muuttamiseen. Yhdistettäessä verkkopakkausta ocLazyload-sovellukseen, olemme löytäneet vakavan voiton AngularJS-projekteille.

Viime viikolla otin tehtävän muuttaa kaikki komponentti / direktiivi-mallin ilmoitukset ja muuttaa ne templateUrl-mallista malliksi. Sen sijaan, että siirrämme kaikki mallit manuaalisesti erillisistä .html-tiedostoistaan ​​vastaaviin JS-tiedostoihin, päätimme käyttää verkkopakkauksen latauslaitetta ja vaatia malleja rivinvaihtoehtoina. Selittääkseni sitä paremmin… anna minun näyttää sinulle, mitä tarkoitan. Seuraava on näyte AngularJS-komponentti:

Kuten näette, ensimmäisessä esimerkissä on komponentti, joka käyttää malliaUrl ladatakseen sen mallin. Tämä on parhaimmillaan ongelmallista, IMO. Se tarkoittaa, että joudut joko ottamaan käyttöön foo / bar / myComponent.html-tiedoston tuotantoon, jotta tuotantosovelluksesi voi ladata mallin fragmentin toisella verkkopyynnöllä saadaksesi sen TAI se tarkoittaa, että joudut lisäämään rakenteen vaihe, joka löytää kaikki templateUrl-esiintymät ja tuo nämä mallit AngularJS-malliinCache. Molemmilla näillä ratkaisuilla on ongelmia.

Ensimmäisen kanssa esiintyvät ongelmat ovat ilmeisiä: jos kaikki tuotetut mallisi vaativat erillisen verkkopyynnön saadakseen ne, yhden yksittäisen näkymän lataaminen vaatisi N-verkkopyyntöjen saamiseksi kaikki näkymät, joissa N on komponenttien lukumäärä / direktiivejä / ngLisäksi mielestäsi.

Toisen ongelmana on, että rakennusvaiheet ovat erittäin käteviä, mutta lataavat kaikki mallisi Web-paketin pääpakettiin. Tämä tarkoittaa, että vaikka aiot ladata komponentin tai sen osan kokonaan laiskaa, niiden mallit ladataan silti pääpakettiisi. Joten et voi hyödyntää kaikkia hyötyjä, jotka saat laiskaalesta.

Kun otetaan huomioon sadat ja sadat mallit, joita meillä on projektissamme, kumpikaan niistä ei ollut toteutettavissa. Tarvitsimme jotain muuta. Tarvitsimme jotain, jonka avulla voimme ladata mallejamme tehokkaasti ilman erillisiä verkkopyyntöjä jokaiselle, samalla kun voimme ladata samat mallit myös laiskaan. Joten päätimme harkita verkkopakkauslataimen käyttöä, jonka avulla voimme vaatia mallipohjamme komponentteihimme HTML / kulmapohjojen rivijonoina.

Edut

Käyttämällä webpack html-loader -sovellusta kaikkien .html-tiedostojen lataamiseen havaitsimme, että pystyimme lataamaan mallimme tehokkaasti, samalla kun annimme meille mahdollisuuden hyödyntää täysimääräisesti lazyloading-sovellusta. Kun käytät mallia: vaatii ('foo / bar / my.html') syntaksi, webpack korvaa vaatimuslausekkeesi toiminnolla, jota kutsutaan ja palautetaan mallin merkkijonolla. Koska malli on nyt toimitettu html-merkkijonona, jos lataat komponentin laiskaan, malli ladataan myös. Juuri sitä tarvitsimme. Löysimme kuitenkin useita muita etuja, joiden löytäminen sai aikaan tämän viestin.

  • Komponentin nopeampi alustus - Kun käytät rivillä olevaa merkkijonoa mallina, komponentti voi alustaa synkronoidusti. AngularJS pyytää mallia mallin välimuistista käyttämällä malliaUrl. Koska mallimuistissa voi jo olla mallipohja välimuistissa tai joudut joutua menemään verkkoon hakemaan sitä, mallin pyytäminen välimuistista on prosessi, joka tapahtuu asynkronisesti. Vaikka malli on jo välimuistissa, templateCache palauttaa jo välimuistiin tallennetun mallin lupauspohjaisen puhelun kautta. Tämä tarkoittaa, että komponentti ei voi alustaa samassa tapahtumasilmukassa. Pyyntö malliCachelle asetetaan aina seuraavalle tapahtumasilmukalle, jopa parhaimmissa tapauksissa. Tämä tarkoittaa, että komponentti voi alkaa alustaa, pyytää mallia ja lopettaa sen alustamisen seuraavassa tapahtumasilmukassa. Mutta kun käytät sisäistä merkkijonoa, komponentilla on jo mallipohja valmis, joten se voi alkaa ja lopettaa sen alustuksen samassa tapahtumasilmukassa. Tämä ei ehkä vaikuta merkittävältä, mutta sillä oli useita odottamattomia tuloksia, jotka meidän piti kompensoida.
    - Komponentit alustuvat nopeammin - mikä kuulostaa mahtavalta, ILMA? No, se on mahtava. Se tarkoittaa kuitenkin, että joillakin komponenteilla, joiden syöttöarvot on aina määritelty alustaessaan, voi rikkoutua, koska samat arvot eivät ehkä ole vielä olemassa. Meillä oli useita komponenttien katkenneita määrittelemättömien syöttösitoutumisarvojen takia. Meidän oli vaihdettava nämä komponentit käyttämään $ watch tai $ onChanges havaitaksesi päivitys tuloarvoihin.
    - Yksikkötestit suoritetaan eri tavalla - Koska kirjoitustestejä vaihdetaan, kun teet synkronista testiä asynkronisen testin kanssa, näiden komponenttien testi voi ehdottomasti muuttua. Esimerkiksi, Mochassa, jos testi on asynk., Injektoit valmiiksi tehdyn menetelmän testiisi ja kutsut siihen, kun testi on valmis. Havaitsimme, että testit suoritettiin nyt synkronoidusti, mikä tarkoitti, että tehty injektiotarve ei ollut enää tarpeen. Edelleen, ja on kiusallista myöntää tämä, mutta meillä oli testejä, jotka kirjoitettiin synkronoidusti, mutta mallien ollessa asynk. Testit, joita EI koskaan ollut onnistuneesti suoritettu. Joten kun sitoin muutokset mallien upottamiseen, testit alkoivat suorittaa onnistuneesti ja läpikäynnin sijasta olivat virheitä !!!! Aluksi luulin, että olen rikkonut kaikki nämä testit. Vasta viiden tunnin ympäröimisen jälkeen tajusin, että nämä testit eivät koskaan läpäisseet. Joten meillä on nyt lisääntynyt testien kattavuus nyt, kun käytämme inline-malleja.
  • html-loader käyttää html-minifinaattoria - Tämä pieni tosiasia heikensi heti mallien kokoa 19%: lla koko sovelluksessa. Tämä on niin erinomaista, ja se on todella jotain, jonka meidän olisi pitänyt tehdä pitkään. Se myös jäsentää malleja ja auttoi meitä löytämään muutama kymmenen mallia, joissa html oli virheellinen. Asiat kuten: luokka "blah", missä = puuttui. Tai attribute = {{jotain}}, josta puuttuu kaikkien sen ympärillä olevat lainausmerkit. Kun korjasin ne, rakennus toimi jälleen.
  • ng-sisällytykset olivat edelleen rikki - Vaikka komponenttimallit toimivat nyt, ng-sisällyttäjät olivat nyt rikki. Meidän piti keksiä jotain heille. Joten rakensimme pienen mukautetun latauslaitteen, joka tuo mallin mallin välimuistiin. Sisäiset käytäntömme kertovat meille, että emme käytä ng-sisällyttämistä, mutta meillä on silti paljon 3 vuotta vanhoja koodeja, jotka sisältävät ne. Joten sen sijaan, että reagoisin kaikkiin tähän sitoumukseen, käytin tätä uutta lataajaa ja menin jokaiseen sovelluksen osioon, jolla on ng-sisällyttäminen, ja latasin kyseisen osan mallin, kuten alla olen osoittanut. Tämä tarkoittaa, että myös ng-sisällyttäjät otetaan huomioon tässä uudessa prosessissa.

Käytetty JSCodeShift

Suosittelen täysin käyttämään webpackia AngularJS-sovelluksissa ja käyttämään html-latauslaitetta mallien siirtämiseen riviin, mikä tarkoittaa, että sinun on vaihdettava templateUrl-ilmentymät mallipohjaisiksi. Koska nämä kaikki näyttävät hyvin erilaisilta, päätin, että tämä oli erittäin hyvä käyttötapa JSCodeShiftille, joka on Facebookin projekti, jonka avulla voit indeksoida AST: n ja korvata ohjelmallisesti kaikki puolestasi ilmenevät esimerkit. Voit ajatella sitä nimellä Etsi ja korvaa steroideja, injektoituina / lisää steroideja. Oli todella helppoa kirjoittaa skripti, joka löysi ja päivitti kaikki nämä mallin Url: n käyttötavat: 'jotkut / url / to.html mallilla: vaadi (). Pystyin vaihtamaan 90% käyttötavoista ohjelmallisesti (noin 700 tiedostoa), ja minun piti viimeistellä 70 käsin. Olisin voinut kirjoittaa koodin näiden 70 muun loppuunsaattamiseksi, mutta tajusin, että voisin tehdä ne helpommin käsin kuin yrittämällä koodata niitä kukin erikseen. Pikahuomautus, AST Explorer on ehdottoman välttämätön, kun käytetään JSCodeShift-ohjelmaa. Ilman sitä en olisi voinut saavuttaa mitään edistystä.

johtopäätös

Hanki AngularJS-sovelluksesi verkkopaketin kokoonpanoon ja anna aikaa saada ne käyttämään html-lataajaa mallien lataamiseen. Käytä mallia templateUrl: n sijasta. Jos et vielä ole, lopeta ng-include-sovelluksen käyttö. Ja sitten, lazyload, lazyload, lazyload! Joskus ihmiset erottavat viivästyneen lastauksen ja laiskan lastauksen. Tarkoitan sekä viivästynyttä lastausta että laiskaa lastausta sanoessani “lazyload”. Se on paras muutos vähentämällä aikaa Ensimerkitykselliseen maalaukseen ja lyhentämällä aikaa sovelluksen saamiseen, jonka kanssa käyttäjä voi olla vuorovaikutuksessa. Onnea. Takaisin pääsi!