AngularJS: `шаблон` супраць` templateUrl`

У апошнія некалькі месяцаў я разглядаў розныя спосабы павышэння эфектыўнасці выканання гіганцкага SPA, над якім працую ў Domo. Мы дасягнулі сур'ёзнага прагрэсу, але, з мільёнам радкоў кода ў адным SPA, некаторыя змены не заўсёды простыя. Адзін з членаў нашай каманды зрабіў адкрыццё, каб дадаць млын загрузкі ў праекты AngularJS, і мы ўкладвалі вялікія сродкі ў гэта. Некалькі розных членаў каманды (Джэйсан і Цім) паглыбляюцца, каб дапамагчы нам вымераць час, які займае наша дадатак, каб цалкам ініцыялізавацца. Мы таксама выкарыстоўвалі webpack для ўпарадкавання зборкі, а таксама для змены некаторых шаблонаў, якія мы выкарыстоўваем. Спалучаючы webpack з ocLazyload, мы знайшлі сур'ёзную выйгрыш для праектаў AngularJS.

На мінулым тыдні я ўзяў на сябе задачу змяніць усе дэкларацыі шаблона кампаненты / дырэктывы і змяніць іх з templateUrl у шаблон. Замест таго, каб уручную перамяшчаць усе шаблоны з асобных .html-файлаў у адпаведныя файлы JS, мы вырашылі выкарыстоўваць загрузчык webpack і запатрабаваць шаблоны ў выглядзе радкоў. Каб лепш растлумачыць гэта ... дазвольце мне паказаць, пра што я. Далей прыклад кампанента AngularJS:

Як бачыце, у першым прыкладзе ёсць кампанент, які выкарыстоўвае templateUrl для загрузкі свайго шаблона. Гэта ў лепшым выпадку IMO. Гэта азначае, што вам трэба альбо разгарнуць файл foo / bar / myComponent.html для вытворчасці, каб ваша дадатак для вытворчасці мог загрузіць фрагмент шаблону праз другі запыт сеткі, інакш гэта азначае, што вам трэба будзе дадаць зборку крок, які знойдзе ўсе асобнікі templateUrl і прывядзе гэтыя шаблоны ў AngCalJS templateCache. У абодвух гэтых рашэнняў ёсць праблемы.

Праблемы з першым відавочныя: калі для ўсіх вашых шаблонаў у вытворчасці неабходны асобны сеткавы запыт, каб атрымаць іх, то для загрузкі любога асобнага выгляду спатрэбіцца N сеткавых запытаў, каб атрымаць усе прагляды, дзе N - колькасць кампанентаў / директивы / ngIncludes у вашым уяўленні.

Праблемы з другім складаюцца ў тым, што крокі зборкі, у той час як гэта вельмі зручна, загружаць усе вашы шаблоны ў ваш асноўны пакет вэб-пакетаў. Гэта азначае, што нават калі вы збіраецеся загрузіць кампанент або цэлы раздзел кампанентаў, іх шаблоны ўсё яшчэ будуць загружацца з вашым асноўным пакетам. Такім чынам, вы не можаце ў поўнай меры скарыстацца перавагамі, якія вы атрымліваеце ад лянівага загрузкі.

Улічваючы шматлікія сотні і сотні шаблонаў, якія мы маем у нашым праекце, ні адзін з іх не быў бы магчымым. Патрэбна было нешта іншае. Нам спатрэбілася тое, што дазволіла б эфектыўна загрузіць нашы шаблоны, без асобных сеткавых запытаў для кожнага, а таксама дазволіць нам цалкам загрузіць тыя ж шаблоны. Таму мы вырашылі паглядзець на выкарыстанне пагрузчыка webpack, які дазволіў бы нам запатрабаваць нашы шаблоны ў нашых кампанентах у выглядзе убудаваных радкоў шаблонаў HTML / Angular.

Перавагі

Выкарыстоўваючы htpa-загрузчык webpack для загрузкі ўсіх файлаў .html, мы выявілі, што нам удалося эфектыўна загрузіць нашы шаблоны, адначасова дазваляючы нам у поўнай меры скарыстацца лянівай загрузкай. Калі вы выкарыстоўваеце сінтаксіс шаблона: need ('foo / bar / my.html'), webpack замяняе вашу заяву патрабуецца функцыяй, якая выклікаецца і вяртаецца радком для шаблона. Паколькі шаблон зараз прадстаўлены ў выглядзе HTML-радка, калі вы lazyload кампанент, шаблон таксама будзе lazyloaded. Гэта менавіта тое, што нам трэба. Аднак мы выявілі некалькі іншых пераваг, адкрыццё якіх падштурхнула гэты пост.

  • Больш хуткая ініцыялізацыя кампанента - Калі вы выкарыстоўваеце ўбудаваную радок у якасці шаблона, кампанент можа ініцыялізаваць сінхронна. Выкарыстоўваючы templateUrl, AngularJS будзе запытаць шаблон ад шаблона Cacheche. Паколькі шаблонCache можа ўжо мець шаблон у кэшы, альбо, магчыма, спатрэбіцца перайсці па ўсёй сеткі, каб атрымаць яго, запыт шаблона з кэша - гэта працэс, які адбываецца асінхронна. Нават калі шаблон ужо знаходзіцца ў кэшы, templateCache верне ўжо кэшаваны шаблон праз выклік на аснове абяцанняў. Гэта азначае, што кампанент не можа ініцыялізаваць адзін і той жа цыкл падзей. Запыт у templateCache заўсёды будзе змешчаны ў наступным цыкле падзей, нават у лепшых сцэнарыях. Гэта азначае, што кампанент можа пачаць ініцыялізаваць, запатрабаваць яго шаблон, а потым скончыць ініцыялізацыю ў наступным цыкле падзей. Але калі вы выкарыстоўваеце ўбудаваны радок, у кампанента ўжо ёсць гатовы шаблон, так што ён можа пачынацца і заканчвацца ініцыялізацыяй у тым самым цыкле падзей. Гэта не можа здацца істотным, але ў нас было некалькі нечаканых вынікаў, якія мы павінны былі кампенсаваць.
    - Кампаненты ініцыялізуюцца хутчэй - што гучыць дзіўна, AIR? Ну, гэта дзіўна. Аднак гэта азначае, што некаторыя вашы кампаненты, якія заўсёды вызначалі свае ўваходныя значэнні, калі іх ініцыялізацыя можа зламацца, выклікаюць, што тыя ж значэнні яшчэ не існуюць. У нас было некалькі разрыў кампанентаў з-за нявызначаных значэнняў увядзення. Мы павінны былі змяніць гэтыя кампаненты, каб выкарыстоўваць $ watch або $ onChanges для выяўлення абнаўлення да ўваходных значэнняў.
    - Тэсты адзінак будуць працаваць па-рознаму - Паколькі тэсты пісання мяняюцца, калі вы робіце сінхронны тэст супраць асінхроннага тэсту, тэст для гэтых кампанентаў можа змена. Напрыклад, у Mocha, калі ваш тэст асінхронны, вы ўводзіце зроблены метад у свой тэст і выклікаеце яго, як толькі тэст будзе зроблены. Мы выявілі, што тэсты зараз выконваюцца сінхронна, а гэта азначае, што неабходнасць уводзіць усё больш не трэба. Далей, і гэта сорамна прызнаць, але ў нас былі тэсты, якія пісаліся сінхронна, аднак, калі шаблоны былі асінхронныя, гэтыя тэсты НІКОЛІ не паспяхова завершаны. Такім чынам, калі я ўнёс змены ў шаблоны, тыя тэсты пачалі паспяхова выконвацца, і замест праходжання яны праваліліся !!!! Спачатку я думаў, што зламаў усе гэтыя выпрабаванні. І толькі пасля таго, як пасля пяці гадзін калючы я зразумеў, што гэтыя тэсты ніколі не праходзяць. Такім чынам, мы на самой справе павялічылі тэставае пакрыццё зараз, калі мы выкарыстоўваем убудаваныя шаблоны.
  • html-loader загружае міні-модуль HTML - гэты маленькі факт імгненна паменшыў памер нашых шаблонаў на 19% ва ўсім дадатку. Гэта настолькі выбітна, і гэта сапраўды тое, што нам трэба было рабіць даўно. Ён таксама разбірае шаблоны і дапамог нам знайсці некалькі дзесяткаў шаблонаў, якія ў іх несапраўдныя HTML. Такія рэчы, як: клас "бла", дзе = адсутнічаў. Ці атрыбут = {{something}}, у якім не хапае двукоссяў ва ўсім. Як толькі я выправіў іх, зборка працавала зноў.
  • ng-include былі па-ранейшаму зламаны - у той час як шаблоны кампанентаў зараз працуюць, ng-include цяпер парушаны. Нам трэба было нешта прыдумаць для іх. Такім чынам, мы стварылі невялікі карыстацкі пагрузчык, які ўвядзе шаблон у templateCache. Нашы ўнутраныя практыкі кажуць нам, каб мы не выкарыстоўвалі ng-include, але ў нас усё яшчэ шмат 3-гадовага кода, які іх утрымлівае. Такім чынам, замест таго, каб перабудаваць усё, што ў гэтым здзяйсненні, я выкарыстаў гэты новы пагрузчык і зайшоў у кожны раздзел прыкладання, які мае ng-include і загрузіў шаблон для гэтага раздзела, як я паказаў ніжэй. Гэта азначае, што ў гэтым новым працэсе таксама паклапаціліся пра ng-include.

Выкарыстоўваецца JSCodeShift

Я цалкам рэкамендую выкарыстоўваць webpack для прыкладання AngularJS і выкарыстоўваць html-пагрузчык, каб прывесці шаблоны ў радок, а значыць, вам трэба будзе змяніць асобнікі templateUrl на асобнікі шаблона. Паколькі ўсе яны выглядаюць зусім па-іншаму, я вырашыў, што гэта вельмі добры варыянт выкарыстання для JSCodeShift, праекта з Facebook, які дазваляе сканіраваць AST і праграмна замяняць усе асобнікі для вас. Вы можаце думаць пра тое, як знайсці і замяніць на пазіцыі, метадалагічнай, ін'екцыйныя ў / больш пазіцыі, метадалагічнай. Вельмі проста напісаць сцэнар, які знайшоў і абнавіў усе гэтыя звычаі templateUrl: 'some / url / to.html з шаблонам: need (). Мне ўдалося змяніць 90% звычаяў ЗША (каля 700 файлаў), і мне давялося скончыць апошнія 70 уручную. Я мог бы напісаць код, каб скончыць гэтыя 70, але я палічыў, што зрабіць гэта лягчэй уручную, чым спрабаваць кадаваць іх кожны паасобку. Кароткая заўвага, AST Explorer з'яўляецца абсалютнай неабходнасцю пры выкарыстанні JSCodeShift. Без гэтага я б не змог дасягнуць ніякага прагрэсу.

Выснова

Усталюйце прыкладанні AngularJS на зборку вэб-пакетаў і ўстаўце час, каб перайсці іх на выкарыстанне HTML-пагрузчыка для загрузкі шаблонаў. Выкарыстоўвайце шаблон замест templateUrl, і калі вы яшчэ гэтага не зрабілі, перастаньце выкарыстоўваць ng-include. А потым, лянівы, лянівы, лянівы! Часам людзі адрозніваюць затрымку загрузкі і лянівую загрузку. Я кажу пра адтэрмінаваную загрузку і лянівую загрузку, калі кажу "лянівы груз". Гэта лепшае змяненне: скараціць час на Першую значную фарбу і скараціць час працы з дадаткам, з якім карыстальнік можа ўзаемадзейнічаць. Поспехаў. Вярнуцца на галаву!