KampinisJS: `šablonas` vs` šablonasUrl`

Per pastaruosius keletą mėnesių ieškojau būdų, kaip pagerinti milžinišką SPA, kuriame dirbu „Domo“. Padarėme didelę pažangą, tačiau turėdami milijoną kodų viename SPA, kai kurie pakeitimai ne visada būna lengvi. Vienas iš mūsų komandos narių padarė atradimą, kad padėtų į „AngularJS“ projektus įtraukti juokingus dalykus, ir mes į tai daug investavome. Keli skirtingi komandos nariai (Jasonas ir Timas) padeda mums įvertinti laiką, kurio reikia mūsų programai visiškai paleisti. Mes taip pat naudojome internetinę pakuotę norėdami supaprastinti kūrimą, taip pat pakeisti kai kuriuos mūsų naudojamus šablonus. Derindami internetinę pakuotę su „ocLazyload“, mes radome rimtą „AngularJS“ projektų laimėjimą.

Praėjusią savaitę aš ėmiausi užduoties pakeisti visas komponentų / direktyvų šablonų deklaracijas ir pakeisti jas iš templateUrl į šabloną. Užuot rankiniu būdu perkėlę visus šablonus iš atskirų .html failų į atitinkamus JS failus, nusprendėme naudoti tinklalapio kroviklį ir reikalauti, kad šablonai būtų įterpti į eilutes. Norėdami tai geriau paaiškinti, leiskite man parodyti, ką turiu galvoje. Tai yra pavyzdinis „AngularJS“ komponentas:

Kaip matote, pirmame pavyzdyje yra komponentas, kuris naudoja „templateUrl“ šablonui įkelti. Tai geriausiu atveju, TJO. Tai reiškia, kad turėsite arba dislokuoti failą „foo / bar / myComponent.html“, kad gamybos programa galėtų įkelti šablono fragmentą per antrą tinklo užklausą, kad jį gautumėte, ARBA tai reiškia, kad turėsite pridėti statinį veiksmas, kuriame bus rasti visi „mallUrl“ egzemplioriai ir tie šablonai bus perkelti į „AngularJS templateCache“. Abu šie sprendimai turi problemų.

Problemos, susijusios su pirmuoju, yra akivaizdžios: jei visiems jūsų gaminamiems šablonams reikėjo atskiros tinklo užklausos, kad juos gautumėte, tada norint įkelti bet kurį rodinį, N tinklo užklausoms gauti reikia visų vaizdų, kur N yra komponentų skaičius / direktyvomis / ngĮtraukia jūsų nuomone.

Antrosios problemos yra ta, kad kūrimo veiksmai, nors ir labai patogūs, įkels visus jūsų šablonus į pagrindinį internetinės pakuotės rinkinį. Tai reiškia, kad net tada, kai ketinate tingiai įkelti komponentą ar visą jo dalį, jų šablonai vis tiek bus įkelti su jūsų pagrindiniu paketu. Taigi, jūs negalite visapusiškai išnaudoti pranašumų, kuriuos gausite iš tinginio įkėlimo.

Atsižvelgiant į daugybę šimtų ir šimtų šablonų, kuriuos turime savo projekte, nė vienas iš jų nebuvo įmanomas. Mums reikėjo kažko kito. Mums reikėjo kažko, kas leistų efektyviai įkelti mūsų šablonus, nereikalaujant atskirų tinklo užklausų kiekvienam, tuo pačiu leisdami visiškai atsikratyti tų pačių šablonų. Taigi nusprendėme naudoti internetinės pakuotės įkėlėją, kuris leistų mums į savo komponentus įtraukti šablonus kaip HTML / kampinių šablonų eilutes.

Pranašumai

Naudodamiesi „webpack html-loader“, kad įkeltume visus .html failus, mes sužinojome, kad mes galime efektyviai įkelti savo šablonus, kartu leisdami mums visapusiškai išnaudoti tinginį įkėlimą. Kai naudojate šabloną: reikalauti ('foo / bar / my.html') sintaksė, internetinė pakuotė pakeičia jūsų reikalavimo pareiškimą funkcija, kuri iškviečiama ir grąžinama kartu su šablono eilute. Kadangi šablonas dabar pateikiamas kaip html eilutė, jei delsite atsisiųsti komponentą, šablonas taip pat bus paimtas. Būtent to mums ir reikėjo. Tačiau mes atradome keletą kitų privalumų, kurių atradimas paskatino šį įrašą.

  • Greitesnė komponento inicializacija - kai kaip šabloną naudojate įterptą eilutę, komponentas gali inicijuoti sinchroniškai. Naudodamas „templateUrl“, „AngularJS“ paprašys šablono iš „mallCache“. Kadangi šabloną talpykloje jau gali būti šablonas talpykloje arba gali reikėti kreiptis į tinklą, kad jį gautumėte, šablono reikalavimas iš talpyklos yra procesas, kuris vyksta asinchroniškai. Net jei šablonas jau yra talpykloje, „templateCache“ grąžins jau išsaugotą šabloną naudodamas pažadą pagrįstą skambutį. Tai reiškia, kad komponentas negali inicijuoti toje pačioje įvykio cikle. Prašymas „templateCache“ visada bus pateikiamas kitoje įvykio kilpoje, net ir geriausiu atveju. Tai reiškia, kad komponentas gali pradėti inicijuoti, paprašyti jo šablono ir tada baigti inicijuoti kitame įvykio cikle. Bet kai naudojate įterptą eilutę, komponentas jau yra paruošęs savo šabloną, todėl jis gali būti pradėtas ir baigtas jo inicijavimu toje pačioje įvykio cikle. Tai gali neatrodyti reikšminga, tačiau turėjome keletą netikėtų rezultatų, kuriuos turėjome kompensuoti. - Komponentai inicijuojami greičiau - kas skamba nuostabiai, ORO? Na, tai nuostabu. Tačiau tai reiškia, kad kai kurių komponentų, kurių įvesties vertės visada buvo apibrėžtos, kai jos gali būti sugadintos, gali būti, kad tų pačių verčių dar nėra. Dėl neapibrėžtų įvesties įrišimo verčių turėjome kelis komponentų lūžius. Turėjome pakeisti tuos komponentus, kad naudotume $ watch arba $ onChanges, kad aptiktume įvesties verčių atnaujinimą. - Vienetų testai vyks skirtingai - Kadangi rašymo testai keičiasi, kai jūs darote sinchroninį testą ar asinchroninį testą, šių komponentų testas tikrai gali pasikeisti. Pvz., Programoje „Mocha“, jei jūsų testas yra asinchroninis, į savo testą įšvirkščiate atliktą metodą ir vadinate jį, kai testas bus atliktas. Mes nustatėme, kad testai dabar buvo atliekami sinchroniškai, o tai reiškė, kad nebereikėjo atlikti injekcijos. Be to, gėdinga tai pripažinti, bet mes turėjome testus, kurie buvo parašyti sinchroniškai, tačiau kadangi šablonai buvo asinchroniniai, tie testai NIEKADA nebuvo sėkmingai atlikti. Taigi, kai aš pasiryžau pakeisti šablonus, šie testai pradėjo sėkmingai veikti, o ne praeiti, jie buvo NETIKRINTI !!!! Iš pradžių maniau, kad sulaužiau visus tuos testus. Tik po 5 valandų pokšto aplink supratau, kad šie testai niekada nebuvo praėję. Taigi, dabar, kai mes naudojame įdėtinius šablonus, padidėjome bandymų aprėptis.
  • „html-loader“ naudoja html minifikatorių - šis faktas akimirksniu sumažino mūsų šablonų dydį 19% visoje programoje. Tai yra nuostabu ir tai tikrai kažkas, ko turėtume daryti jau seniai. Tai taip pat analizuoja šablonus ir padėjo mums surasti keliasdešimt šablonų, kuriuose html buvo netinkamas. Dalykai, tokie kaip: klasė „blah“, kur trūko =. Arba atributas = {{kažkas}}, kurio trūksta kabutėms. Kai aš juos ištaisiau, pastatas vėl veikė.
  • „ng-include“ vis dar buvo sulaužyti - kol komponentų šablonai veikė, „ng-include“ buvo sulaužyti. Mums reikėjo sugalvoti ką nors jiems. Taigi mes sukūrėme nedidelį pasirinktinį krautuvą, kuris įneš šabloną į „mallCache“. Vidaus praktika liepia nenaudoti „ng-include“, tačiau vis tiek turime daug 3 metų ir vyresnių kodų, kuriuose jie yra. Taigi, užuot reagavęs į visa tai, kas buvo šiame įsipareigojime, aš panaudojau šį naują krautuvą ir nuėjau į kiekvieną programos skyrių, kuriame yra „ng-include“, ir įkeliau tos dalies šabloną, kaip aš parodžiau žemiau. Tai reiškia, kad į šį naują procesą taip pat atsižvelgiama įtraukiant ng-įtraukimus.

Naudota „JSCodeShift“

Aš visiškai rekomenduoju naudoti „AngularJS“ programų „webpack“ ir naudoti „html-loader“, kad jūsų šablonai būtų įterpti į tinklą, o tai reiškia, kad jums reikės pakeisti „templateUrl“ egzempliorius į šabloninius egzempliorius. Kadangi visi jie atrodo labai skirtingai, nusprendžiau, kad tai buvo labai geras „JSCodeShift“, „Facebook“ projekto, leidžiančio nuskaityti AST ir programiškai pakeisti visus egzempliorius, naudojimo atvejai. Galite galvoti apie tai kaip „Steroidų radimas ir pakeitimas“, įpurškiami su daugiau steroidų. Parašyti scenarijų, kuris rado ir atnaujino visus šiuos „mallUrl“ papročius: „kai kurie / url / to.html su šablonu: reikalauti (), buvo tikrai paprasta. Aš sugebėjau programiškai pakeisti 90% įpročių (apie 700 failų), o paskutinius 70 turėjau baigti rankomis. Aš galėčiau parašyti kodą, kad baigčiau tuos kitus 70, bet aš supratau, kad galėčiau tai padaryti lengviau ranka, nei bandydamas juos užkoduoti atskirai. Trumpai tariant, AST Explorer yra būtinas dalykas naudojant JSCodeShift. Be jo nebūčiau galėjęs padaryti jokios pažangos.

Išvada

Gaukite „AngularJS“ programas įdėdami į internetinę pakuotę ir skirkite laiko joms naudoti, naudodami html-loader, kad įkeltumėte savo šablonus. Naudokite šabloną, o ne šablonąUrl. Jei to dar nepadarėte, nustokite naudoti „ng-include“. Tada lazyload, lazyload, lazyload! Kartais žmonės išskiria atidėtą ir tingų pakrovimą. Aš turiu omenyje ir atidėtą, ir tingų pakrovimą, kai sakau „tingus įkėlimas“. Tai yra geriausias jūsų pakeitimas sumažinus laiką iki pirmojo prasmingo dažymo ir sutrumpinant laiką, kurį turi programa, su kuria vartotojas gali bendrauti. Sėkmės. Atgal ant galvos!